最近面试的时候有些会问到什么情况下会导致锁表,我查阅了一下资料,汇总情况如下,但可能也不一定齐全。以下情况都在RR事务隔离级别下测试。

1.update语句的where条件字段没有索引

mysql什么时候会产生锁 mysql什么时候会锁表_字段


上面就是一个update语句例子,name字段是没有索引的

mysql什么时候会产生锁 mysql什么时候会锁表_mysql什么时候会产生锁_02


实际代码里xml里的语句是上面这样的,在第一个事务执行这个更新时,会锁表,执行期间,第二个事务执行这个sql会被阻塞,需等待第一个执行完后,第二个才会执行。

解决办法:给name字段加索引,第一个事务就不会锁表了。2.MySQL在Select …for update语句时(当前读),用到索引可用时使用行锁索,不可用时使用表锁

下面两个查询,empno是主键,两次查询是没问题的。

mysql什么时候会产生锁 mysql什么时候会锁表_mysql_03


mysql什么时候会产生锁 mysql什么时候会锁表_字段_04

下面根据dname去查,dname是没有索引的。

mysql什么时候会产生锁 mysql什么时候会锁表_字段_05


另外一个事务根据empno去查,被阻塞

mysql什么时候会产生锁 mysql什么时候会锁表_mysql_06


解决办法:给dname字段加索引,这个和第一个情况是差不多的。

这里还有情况:如果查询的empno(例如empno=7521)是dname=‘SALES’里的还是会被锁住,因为第一个查询语句就是锁的dname=‘SALES’的数据,如果查询的empno(上面的7566)不是dname=‘SALES’里的不会被阻塞。

3.索引选择的问题
跟着上面的第二个问题,如果表中dname=‘SALES’的数据够多(大概20%),锁着这些数据的时候,mysql可能会升级为锁表(mysql认为表锁可能效率更高)。

mysql什么时候会产生锁 mysql什么时候会锁表_字段_07


怎么解决:强制走索引

mysql什么时候会产生锁 mysql什么时候会锁表_mysql什么时候会产生锁_08


或者有其他的条件来缩小数据范围

mysql什么时候会产生锁 mysql什么时候会锁表_mysql_09


如果只是update语句,不会因为索引选择的问题而升级为表锁的,它还是会走索引,所以update没有这个问题。

mysql什么时候会产生锁 mysql什么时候会锁表_字段_10


总结在这

mysql什么时候会产生锁 mysql什么时候会锁表_字段_11