今天才知道,Redis
从2.8.12
版本开始支持“ROLE
”命令了。通过“ROLE
”命令,可以得到当前Redis
的角色是“master
”,“slave
”或者“sentinel
”。回想我们一年前做Redis
监控程序时,还要通过“info
”命令得到整个Redis
状态,然后再解析“Role
”这个关键字,才能得到是什么角色,实在有点麻烦。如果有机会,应该升级一下监控程序,一旦发现是2.8.12
版本,就直接用“ROLE
”命令好了。
月份:2014年12月
2014年终总结
2014年就要走完了,是时候总结一下了:
(1)chinadtrace
:申请的第一个微信公众号,建立了第一个介绍DTrace
的中文网站:http://chinadtrace.org/;
(2)8月昆山之行:一场说走就走的旅行;
(3)100个gdb小技巧:与hellogcc伙伴们合作的项目。历时半年,今天发布1.0版本。电子书下载地址;
(4)公司被并购:将来适当的时候会详细写一下这段过程;
(5)拥有了属于自己的域名:https://nanxiao.me/;
(6)为开源项目redis
和unixODBC
贡献patch
;
(7)十一之行:难忘的回家之旅;
(8)在影院看了两部没白花钱的电影:《白日焰火》和《黄金时代》;
(9)阅读了几本还不错的书;
(10)享受到了4G网络。
100个gdb小技巧(v1.0).pdf
从hellogcc于今年6月份开启《100个gdb小技巧》这个项目,我便参与其中。截至到这周末,一共收集了100
个实用的gdb
小技巧。我利用这个周末时间,把它制作成了一本pdf
的电子书,方便大家下载和使用。当然,100
不是终点,未来这个项目还会发展下去,还会有2.0
,3.0
的版本出来。Stay tuned!
P.S.:下载地址。
unixODBC驱动链接的数据库客户端和程序直接链接的数据库客户端库一定要一致
这两天调试了一个诡异的问题,使用unixODBC
连接MySQL
数据库,最后程序core dump
在MySQL 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
数据库客户端库)。
这个坑一定要记住!
一键编译安装gcc
本文原载于我在hellogcc
上的文章。
今天看到一篇文章,作者通过一个shell
脚本和一个Makefile
,可以自动下载需要的所有安装包并且自动编译gcc
:
$ # Download the scripts using wget.
$ mkdir /opt/gcc-4.9.2
$ cd /opt/gcc-4.9.2
$ wget http://projects.joelinoff.com/gcc-4.9.2/bld.sh
$ wget http://projects.joelinoff.com/gcc-4.9.2/Makefile
$ chmod a+x bld.sh
$ make
[output snipped]
$ # The compiler is installed in /opt/gcc-4.9.2/rtf/bin
我试了一下,果然很方便。只要有一台可以联网的机器,就可以了。感兴趣的朋友可以试一试。
P.S.:
(1)编译libiconv
时可能会有“'gets' undeclared here
“错误,请参考这篇文章。
(2)如果机器是64
位的,但是缺少32
位的库文件。这样在编译gcc
时会出现错误:“configure: error: I suspect your system does not have 32-bit developement libraries (libc and headers). If you have them, rerun configure with --enable-multilib. If you do not have them, and want to build a 64-bit-only compiler, rerun configure with --disable-multilib.
”。提示需要配置“--disable-multilib
”。
ODBC中的三种变量类型
无论是使用ODBC
的新手或老兵,看到SQLCHAR
、SOL_C_CHAR
和SQL_CHAR
,可能都会有些糊涂。它们之间的区别到底是什么呢?
(1)第一种是ODBC
定义的数据类型(像SQLCHAR
):SQL
开头,后面跟着一系列大写字符,但是没有下划线。这种数据类型定义在sqltypes.h
中,比如:
typedef signed short int SQLSMALLINT;
typedef SQLSMALLINT SQLRETURN;
#if (ODBCVER >= 0x0300)
typedef void * SQLHANDLE;
......
#endif
这种数据类型可以用来定义变量,ODBC
API
的变量类型都是这种类型:
#if (ODBCVER >= 0x0300)
SQLRETURN SQL_API SQLAllocHandle(SQLSMALLINT HandleType,
SQLHANDLE InputHandle, SQLHANDLE *OutputHandle);
#endif
这样做的好处是ODBC
提供了一套自己的变量类型,相当于封装了一层,使用者不用关心底层具体的变量类型实现细节。即使底层的变量类型做了修改,使用者的代码也不用做任何改动。
这种数据类型和C
语言数据类型的映射如下:
ODBC 类型 | C 类型 |
---|---|
SQLCHAR | char |
SQLSCHAR | signed char |
SQLINTEGER | long int |
… | … |
(2)第二种是C
语言的数据类型编码(SQL_C_CHAR
)。他们并不是真正的数据类型,而是针对上面提到的的ODBC
定义的数据类型的编码,所以不能用来定义变量。他们可以用作ODBC
API
的参数。这种数据类型定义在sqlext.h
中,比如:
#define SQL_C_CHAR SQL_CHAR /* CHAR, VARCHAR, DECIMAL, NUMERIC */
#define SQL_C_LONG SQL_INTEGER /* INTEGER */
#define SQL_C_SHORT SQL_SMALLINT /* SMALLINT */
#define SQL_C_FLOAT SQL_REAL /* REAL */
#define SQL_C_DOUBLE SQL_DOUBLE /* FLOAT, DOUBLE */
这种数据类型和ODBC
数据类型的映射如下:
整数编码 | ODBC 类型 |
---|---|
SQL_C_CHAR | SQLCHAR |
SQL_S_STINYINT | SQLSCHAR |
SQL_C_SLONG | SQLINTEGER |
… | … |
(3)第三种是SQL
数据类型编码。同第二种一样,他们也不是真正的数据类型,而是提供SQL
数据类型和编程语言数据类型的关联,因为也是数字编码,所以也不能用来定义变量。他们可以用作ODBC
API
的参数。这种数据类型定义在sqlext.h
中,比如:
#define SQL_C_CHAR SQL_CHAR /* CHAR, VARCHAR, DECIMAL, NUMERIC */
#define SQL_C_LONG SQL_INTEGER /* INTEGER */
#define SQL_C_SHORT SQL_SMALLINT /* SMALLINT */
#define SQL_C_FLOAT SQL_REAL /* REAL */
#define SQL_C_DOUBLE SQL_DOUBLE /* FLOAT, DOUBLE */
这种数据类型和SQL
数据类型的映射如下:
整数编码 | SQL类型 |
---|---|
SQL_CHAR | Char(n) |
SQL_VARCHAR | Varchar(n) |
SQL_SMALLINT | Smallint |
… | … |
使用MySQL ODBC一次提交多条SQL语句
MySQL ODBC
从3.51.18
版本开始支持一次提交多个语句(请参考:http://dev.mysql.com/doc/connector-odbc/en/connector-odbc-configuration-connection-parameters.html)。方法是要给odbc.ini
的数据源配置值为67108864
的option
。如下图所示:
[DB1]
......
option = 67108864
注意这个option
一定要配在odbc.ini
的数据源上,而不能配在odbcinst.ini
的驱动上。因为MySQL
的ODBC
代码只从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
查看建立连接时的抓包: