最近在專案中發現了事務之間的死鎖問題,所以研究了一下MySQL鎖機制,並且延伸到了MVCC等周邊知識,我只在這裡介紹一下開發中可能遇到的問題,具體內容推薦閱讀《高效能MySQL》。
前言:mysql有兩種鎖機制——讀鎖(共享鎖)和寫鎖,意思就是一個程式獲取讀鎖的話,所有程式都可以進行讀,但不可以寫,如果一個程式獲取了寫鎖,那除了這個程式之外其他程式都不可以進行讀寫。由於myisam不存在死鎖的問題也不支援事務,所以這裡主要介紹關於innodb的鎖機制。
1、兩個程式同時訪問資料庫中的同一條記錄,一個是讀,一個是寫,在mysql會怎樣執行呢?
在myisam中,會先進行寫鎖(鎖表),然後進行寫操作,讀操作在後面阻塞,等寫操作完成釋放鎖,才進行讀操作,為什麼這樣呢,因為在mysql中寫操作優先順序高於讀操作,甚至有的時候寫操作來的比讀操作來得晚也會排在讀操作前執行,而在innodb中則是同時進行,互相不干擾,這就是MVCC(多版本控制)的功勞。
2、在事務中的死鎖?
//SQL1 start transaction; update test set name=`wjw` where id=1; update test set name=`wy` where id=2; commit;
//SQL2 start transaction; update test set name=`wjw` where id=2; update test set name=`wy` where id=1; commit;
上面兩個事務,如果他們都執行完第一條sql的時候,第二個事務執行了第二條sql,但是第一個事務中已經對id=1的行進行了鎖定,然後就會等待第一個事務commit,當第一個事務執行第二個sql的時候發現第二個事務已經對id=2的行進行了鎖定,所以會等待第二個事務commit,結果就造成了死鎖,這裡有一個知識點,就是事務是一個整體,只有全執行完了才算結束,這也是為什麼執行完一條sql後還是鎖定行。
解決辦法:死鎖在很多資料庫中都存在,解決辦法就是避免死鎖,比如上面的例子,你可以把兩個事務的sql數序寫成一樣的,第一個更新id=1的,第二個更新id=1的。在innodb中,它會自動判斷是否發生了死鎖,如果發生了,它會讓其中一個事務成功,另一個事務報錯deadlocked
3、如果兩個人同時編輯一篇文章衝突了怎麼辦?
當第一個人編輯完就提交了,可是第二個人不知道,他編輯完也提交了,這樣就把第一個人編輯的內容覆蓋了,這就引出了樂觀離線鎖概念,具體內容可以看我另一篇文章===>12306搶票問題
PS:表達能力有限,有任何問題,歡迎交流