unixODBC驱动链接的数据库客户端和程序直接链接的数据库客户端库一定要一致

这两天调试了一个诡异的问题,使用unixODBC连接MySQL数据库,最后程序core dumpMySQL client代码的fill_ird_data_lengths函数:

void fill_ird_data_lengths(DESC *ird, ulong *lengths, uint fields)
{
  ......
  assert(fields == ird->count);
}

fileds是一个很离谱的数,一看就像是内存值被破坏了。

经过艰苦的单步调试,最后查出的问题是unixODBC驱动链接的MySQL数据库客户端库和程序直接链接的MySQL数据库客户端库不一样(因为程序还没有完全改完,有一部分code还会直接调用MySQL数据库客户端库)。

这个坑一定要记住!

使用MySQL ODBC一次提交多条SQL语句

MySQL ODBC3.51.18版本开始支持一次提交多个语句(请参考:http://dev.mysql.com/doc/connector-odbc/en/connector-odbc-configuration-connection-parameters.html)。方法是要给odbc.ini的数据源配置值为67108864option。如下图所示:

[DB1]
......
option = 67108864

注意这个option一定要配在odbc.ini的数据源上,而不能配在odbcinst.ini的驱动上。因为MySQLODBC代码只从odbc.ini文件查找option

int ds_lookup(DataSource *ds)
{
    ......
    for (used= 0; used < size; used += sqlwcharlen(entries) + 1,
                             entries += sqlwcharlen(entries) + 1)
      {
        int valsize;
        ds_map_param(ds, entries, &dest, &intdest, &booldest);

        if ((valsize= SQLGetPrivateProfileStringW(ds->name, entries, W_EMPTY,
                                                  val, ODBCDATASOURCE_STRLEN,
                                                  W_ODBC_INI)) < 0)
        {
          rc= 1;
          goto end;
        }
        else if (!valsize)
          /* skip blanks */;
        else if (dest && !*dest)
          ds_set_strnattr(dest, val, valsize);
        else if (intdest)
          *intdest= sqlwchartoul(val, NULL);
        else if (booldest)
          *booldest= sqlwchartoul(val, NULL) > 0;
        else if (!sqlwcharcasecmp(W_OPTION, entries))
          ds_set_options(ds, ds_get_options(ds) | sqlwchartoul(val, NULL));

        RESTORE_MODE();
      }

    ......
}

验证这个配置项是否成功,可以通过wireshark查看建立连接时的抓包:

捕获
可以看到“Multiple Statements”值为1,设置成功。