前天和同事饭后散步的时候他说使用for update如果没有命中索引就会锁表,刚好最近要写类似的代码,听了之后心有戚戚,于是乎来尝试一下。
表结构:
数据:
第一个事务:SELECT * FROM student WHERE
no= '325985' FOR UPDATE;
第二个事务:SELECT * FROM student WHERE
no= '456325' FOR UPDATE;
可以看的出来,在第一个事务中,我只锁了no为325985的记录,但在第二个事务中,no为456325却无法查询,说明没有命中索引确实会锁表。
加上索引后试试:
第一个事务:
第二个事务:
都可以查出来,说明没有锁表。
还有一种特殊情况,就是如果where之后的条件是索引,但数据是不存在的,这种情况会锁表吗?推论:既然数据不存在,那么也无法命中索引,那么也会锁表。不过不能光想不做,让我们一起试试吧。
加一个联合唯一索引:
第一个事务:SELECT * FROM student WHERE
name= '李不飞' AND
no= '325985' AND gender = 2 AND class = 13 AND grade = 3 FOR UPDATE;
第二个事务:SELECT * FROM student WHERE
name= '李飞飞' AND
no= '325985' AND gender = 2 AND class = 13 AND grade = 3 FOR UPDATE;
看来我的推论是错误的,如果这条数据不存在,是不会锁表的。
结论:如果for update没有命中索引会锁表。
补充一点,update更新语句和for update机制一样,没有命中索引,同样会锁表。