从MySQL Signal 14 Warning看MySQL的线程信号处理模型

 原文链接:http://blog.inkernel.info/archives/17.html


“MySQL Signal 14 Warning”这个问题来源于在使用我们的存储引擎时会在MySQL的log中发现大量的“Got signal 14 from

thread 0”的警告信息,并且我们移植的MySQL测试用例也会不确定地失败,除非显式指定忽略警告信息,但这也导致一些有用

的warning也被忽略了。在很长的一段时间里我们都没有能够找到真实的原因,后来我才在阅读了MySQL上层的代码和我们的代码,

以及加上一些trace后确定了问题的所在。这其实是我们没有按照MySQL预想的方式使用后台线程导致,但在MySQL的手册和网站

上似乎也没有发现这方面的tips。

MySQL的线程工作模型是(From MySQL Doc):

1、Connection manager threads handle client connection requests on the network interfaces that the server
 listens to.

2、A signal thread handles all signals. This thread also normally handles alarms and calls process_alarm()
to force timeouts on connections that have been idle too long.

3、If mysqld is compiled with -DUSE_ALARM_THREAD, a dedicated thread that handles alarms is created.
This is only used on some systems where there are problems with sigwait() or if you want to use the thr_alarm()
code in your application without a dedicated signal handling thread.

从mysql的main函数中可以看到,虽然mysql的主线程注册了SIGALARM的信号处理函数,但是实际上mysql是采用在指定的线程

中同步的方式处理异步信号的,即主线程在系统初始化时先进行信号的初始化,包括设置主线程的信号掩码,以统一抛给信号处理

线程去处理,主线程的信号掩码会被它的所有子线程继承,之后进程收到的信号都会由信号处理线程去处理。但前提是所有的子线

程都继承了主线程的信号掩码,否则异步信号总能够传递给进程。

我们的问题出在有两个后台线程是在静态变量中初始化和启动的,这时候mysql的主线程根本还没进行信号掩码的设置,所以SIGALARM这个

本来应该由信号处理线程处理的信号,却通过我们的后台线程handle给了MySQL的主进程,并调用信号处理函数打出这个warning。

后来发邮件给MySQL的开发人员(http://lists.mysql.com/internals/38057), 他们确认了我的理解是对的, 并且指出了我们这样使用线程
可能导致其他的问题, 包括:

1、在静态变量的构造函数中执行代码,可能导致代码执行权限被提升,有安全问题;

 2、如果把存储引擎编译成动态链接库的形式的话,只有init()回调函数会被调用到,静态变量的构造函数永远不会被执行。

他们的建议是:Please don't execute any code before mysql asks you to initialide the engine.

而innodb默认也有几个后台的io线程,之所以没这个问题,是因为这些后台线程是在innobase_init()函数中创建的,这些线程都继承了主线程的信号掩码。
新文章链接:http://blog.inkernel.info/archives/17.html

posted on 2011-03-06 17:16  Swimming Fish  阅读(419)  评论(0编辑  收藏  举报

导航