回顾一下线上数据库(5.1.68)的CASE,高峰期的时候出现了大量的thread_running,发现基本上线程处于deadlock状态,涉及到的只有一张表,并且只有一行:

table a

(`id` smallint(5) unsigned NOT NULL DEFAULT'0',

`key` varchar(32) NOT NULL,

`value` varchar(32) NOT NULL,

`time` int(10) unsigned NOT NUL)engine=innodb;

数据库的版本是5.1.68 innodb-plugin;原来的逻辑是:

Lock table awrite;读取并更新该表;unlocktable;

后来改了逻辑begin;select id,key,value from a for update;更新;commit;

而出现问题的时候这2个逻辑同时存在,这就造成了MySQL Server层和Storage层的死锁;

一种时序如下

Session1:

begin;

Select * from a for update ; -- lock everyrow in execlusive mode


Session2:

Lock table a write; -- lock table a in server


Session2:

Update a set key=xxx where id=xxx –-holdserver lock and acquire row lock

Session1:

同上;--hold row lock andacquire server lock

因此发生了死锁;原因是RD发布代码只发布了一部分,后来回滚解决了;另外一个Solution就是将该表改成MyISAM引擎,这样就破除了row lock;

不过这个问题在5.5通过引入MDL解决了,当这里session2执行lock table t write时会被阻塞在:Waiting for table metadata lock 上,打破了死锁条件