故事背景
今天朋友說操做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