故事背景
今天朋友说操做mysql超时了,我首先想到的是环境的问题。我问是否是数据源配错了,他给个人答案是否认的。而后查了下日志:java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction。跟踪到是下面SQL致使的表锁 SELECT * FROM t_cms_promotion t WHERE t.pro_des = #{description} FOR UPDATE
innodb锁机制
innodb默认是行锁,前提条件是创建在索引之上的。若是筛选条件没有创建索引,会降级到表锁。即
若是where条件中的字段都加了索引,则加的是行锁;不然加的是表锁。下面咱们从几个方面对比下行锁和表锁
表1
对比方向 |
行锁 |
表锁 |
锁定粒度 |
小 |
大 |
是否会发生死锁 |
会 |
不会 |
锁冲突几率 |
小 |
大 |
并发数 |
多 |
少 |
开销 |
小 |
大 |
在加锁的时候,mysql有读锁和写锁,为了说明如何使用,小编在此举如下例子:
- 读锁(共享锁):容许其余线程上读锁,可是不容许上写锁;
SELECT * FROM t_cms_promotion t WHERE t.pro_id = ?
LOCK IN SHARE MODE
- 写锁(排他锁):不容许其余线程上任何锁。
SELECT * FROM t_cms_promotion t WHERE t.pro_id = ?
FOR UPDATE
注:若是让以上SQL语句上行锁,查询条件pro_id须要创建索引java