MySQL中select * for update鎖表的范圍
MySQL中select * for update鎖表的問題
由於InnoDB預設是Row-Level Lock,所以只有「明確」的指定主鍵,MySQL才會執行Row lock (只鎖住被選取的資料例) ,否則MySQL將會執行Table
Lock (將整個資料表單給鎖住)。 舉個例子: 假設有個表單products ,里面有id跟name二個欄位,id是主鍵。
例1: (明確指定主鍵,並且有此筆資料,row lock)
SELECT * FROM products WHERE id='3' FOR UPDATE;
SELECT * FROM products WHERE id='3' and type=1 FOR UPDATE;
例2: (明確指定主鍵,若查無此筆資料,無lock)
SELECT * FROM products WHERE id='-1' FOR UPDATE;
例2: (無主鍵,table lock)
SELECT * FROM products WHERE name='Mouse' FOR UPDATE;
例3: (主鍵不明確,table lock)
SELECT * FROM products WHERE id<>'3' FOR UPDATE;
例4: (主鍵不明確,table lock)
SELECT * FROM products WHERE id LIKE '3' FOR UPDATE;
注1: FOR UPDATE僅適用於InnoDB,且必須在交易區塊(BEGIN/COMMIT)中才能生效。
注2: 要測試鎖定的狀況,可以利用MySQL的Command Mode ,開二個視窗來做測試。
在MySql 5.0中測試確實是這樣的
另外:MyAsim 只支持表級鎖,InnerDB支持行級鎖 添加了(行級鎖/表級鎖)鎖的數據不能被其它事務再鎖定,也不被其它事務修改
(修改、刪除) 。是表級鎖時,不管是否查詢到記錄,都會鎖定表。
-------------------------------------------------------------------------------------------------------------------------
今天碰到詭異的表死鎖問題。
首先Tomcat報錯:
Caused by: com.MySQL.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
使用 show engine innodb status .
查看mysql死鎖。
發現是 update語句中把子查詢中的表給死鎖了。比如
update table_a set comments = (select count(1) from table_b where id = table_a.id) where id = 123;
把table_b給鎖住了。
搜索了一個,發現是mysql的問題。
http://shen2.cn/2013/06/sub-query-in-update-locked-table/
最后發現這個不是mysql bug,
mysql 默認的隔離級別是REPEATABLE-READ,oracle默認數據隔離級別是 READ-COMMITTED 。所以在mysq中
update ... select * from
insert into .... select * from
這些語句中,都會鎖住子表的row.
將mysql 隔離級別改成
SET session TRANSACTION ISOLATION LEVEL READ COMMITTED;
問題就解決了。
-------------------------------------------------------------------------------------------------------------------------------------------
解鎖
第一種
show processlist;
找到鎖進程,kill id ;
第二種
mysql>UNLOCK TABLES;
鎖表
鎖定數據表,避免在備份過程中,表被更新
mysql>LOCK TABLES tbl_name READ;
為表增加一個寫鎖定:
mysql>LOCK TABLES tbl_name WRITE;
以上文章非原創,只做收藏用。