最近面试的时候有些会问到什么情况下会导致锁表,我查阅了一下资料,汇总情况如下,但可能也不一定齐全。以下情况都在RR事务隔离级别下测试。
1.update语句的where条件字段没有索引
上面就是一个update语句例子,name字段是没有索引的
实际代码里xml里的语句是上面这样的,在第一个事务执行这个更新时,会锁表,执行期间,第二个事务执行这个sql会被阻塞,需等待第一个执行完后,第二个才会执行。
解决办法:给name字段加索引,第一个事务就不会锁表了。2.MySQL在Select …for update语句时(当前读),用到索引可用时使用行锁索,不可用时使用表锁
下面两个查询,empno是主键,两次查询是没问题的。
下面根据dname去查,dname是没有索引的。
另外一个事务根据empno去查,被阻塞
解决办法:给dname字段加索引,这个和第一个情况是差不多的。
这里还有情况:如果查询的empno(例如empno=7521)是dname=‘SALES’里的还是会被锁住,因为第一个查询语句就是锁的dname=‘SALES’的数据,如果查询的empno(上面的7566)不是dname=‘SALES’里的不会被阻塞。
3.索引选择的问题
跟着上面的第二个问题,如果表中dname=‘SALES’的数据够多(大概20%),锁着这些数据的时候,mysql可能会升级为锁表(mysql认为表锁可能效率更高)。
怎么解决:强制走索引
或者有其他的条件来缩小数据范围
如果只是update语句,不会因为索引选择的问题而升级为表锁的,它还是会走索引,所以update没有这个问题。
总结在这