问题
服务器变量table_locks_immediate和 table_locks_waited#?它们保持多大的比例是合适的?
背景
table_locks_immediate表示可以立即获取锁的查询次数, table_locks_waited表示不能立即获取锁的次数;
Session 1
Session 2
lock tables t1 read;
(table_locks_immediate+1)
update t1 set y=1 where id=1;
(locked并且table_locks_waited+1)
上面这个例子很简单,session 1加了表所,但是session 2要更新,获取表锁失败。
异象 www.2cto.com
Session 1
Session 2
lock tables t1 write;
(table_locks_immediate+1)
update t1 set y=1 where id=1;
(locked但table_locks_waited不变)
这个例子看上去像个bug,session 1锁表,session 2试图更新这个表,被锁住了,但是table_locks_waited没有加1,而且查看table_locks_immediate也不变。
其原因是5.5新引入的metadata lock(MDL),对表的访问都需要获取MDL。在这个例子中,session 1拥有一个排他MDL,因此Session2是被锁在获取MDL的阶段。
由于MDL是在获取表锁之前,因此在session 2被lock的时,上述两个变量都不变。
www.2cto.com
什么情况下会触发table_locks_waited
从上面这个例子看,引入MDL以后,table_locks_waited并不容易触发。除非应用主动作lock tables t read。
我们用并发压力,两个线程分别执行update t1 set y=y+1 where id=1;各5000次。
若t1为MyISAM表,MyISAM是表锁,在并发压力下,是会导致table_locks_waited急剧增加。
而在InnoDB表,由于是行锁,因此获取表锁这个逻辑都能顺利通过,因此table_locks_waited不变。
table_locks_waited多少合适
回到初始的问题,若库中都是InnoDB的表,在5.5以后,table_locks_waited这个值应该很小。在
mysqldump导出表时,会执行lock table,可能导致此值增加。其他情况下,若这个值有变,说明应用端主动作了lock table,这个在InnoDB表上是不需要的,需要应用修改。