看mysql官方文檔:InnoDB事務模型和鎖定
知識儲備:
1、官方文檔上說mysql是支持非鎖定讀的;這個功能是這樣實現的,如果事務a 要對行的數據進行更新的話,那么事務a要得到行的x鎖,並把這一行
之前的樣子記錄在undo log里面,這樣一來如果a 事務rollback 了就可以通過undo log 來恢復到之前的樣子;說白了非鎖定的一致性讀就是讀的
行的undo log 中的內容,所以這貨根本就不用上鎖。
2、在mysql中事務與鎖的關系:
1、事務開始之后申請鎖。
2、得到鎖之后才進行相關的操作,事務提交或回滾之后才會去釋放申請到的鎖。
3、如果想要select 語句也加上s鎖可以在select 后面加上lock in share mode 子句。
4、mysql支持意向鎖、意向鎖是在表級別上的;
5、innodb 對鎖的分配方式:
1、innodb 的鎖是需要用到的時候才會去分配,並是一次性要把事務要用到的鎖分配完成后才去執行事務。
2、對鎖的申請請求是放在一個隊列當中的,請申請的先得到。
例子:一個lock in share mode 引起的死鎖問題:
1、准備環境:
create database tempdb; use tempdb; create table t(x int); insert into t(x) values(1);
2、事務一執行如下語句:
mysql> start transaction; Query OK, 0 rows affected (0.00 sec) mysql> select * from t where x=1 lock in share mode; +------+ | x | +------+ | 1 | +------+ 1 row in set (0.00 sec)
3、事務二執行如下語句:
mysql> start transaction; Query OK, 0 rows affected (0.00 sec) mysql> delete from t where x=1;
4、接着事務一又執行如下語句:
mysql> delete from t where x=1;
5、最后mysql 監控到死鎖
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
原因分析:
1、事務一先是得到了x=1 這一行上的s 鎖;
2、事務二要去申請x=1 這一行上的x鎖,由於事務一已經得到了s鎖,所以它要等待事務一釋放s鎖。
3、事務一又想去申請x=1 這一行上的x鎖,由於事務二的申請在事務一的前面發起,所以它要等待事務二完成后才能得到。
由以上分析可知,事務一,事務二產生了相互等待;進而死鎖產生。
因此,InnoDB對客戶端A產生一個錯誤,並且釋放它的鎖定。在那一點
上,客戶端B的鎖定請求可以被許可,並且客戶端B從表中刪除行。