MySQL - 共享锁和排它锁初探
文章目錄
- 生猛干貨
- 官方文檔
- 事務隔離級別
- 共享鎖 VS 排他鎖的區別
- SELECT ... FOR UPDATE 排它鎖 演示
- SELECT ... LOCK IN SHARE MODE 共享鎖 演示
- 搞定MySQL
生猛干貨
帶你搞定MySQL實戰,輕松對應海量業務處理及高并發需求,從容應對大場面試
官方文檔
鎖定某一行可以用lock in share mode(共享鎖) 和for update(排它鎖)
官方文檔:
https://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html
大體過一下
如果你在查詢數據,然后在同一個事務里插入或者修改相關的數據,常規的 select 語句不會提供足夠的保護。其他的事務可以修改或者刪除你正在查詢的行。
InnoDB 支持兩種可以提供安全機制的讀取鎖:
-
SELECT … LOCK IN SHARE MODE 在讀取的行上設置一個共享鎖,其他的session可以讀這些行,但在你的事務提交之前不可以修改它們。如果這些行里有被其他的還沒有提交的事務修改,你的查詢會等到那個事務結束之后使用最新的值
-
索引搜索遇到的記錄,SELECT … FOR UPDATE 會鎖住行及任何關聯的索引條目,和你對那些行執行 update 語句相同。其他的事務會被阻塞在對這些行執行 update 操作,獲取共享鎖,或從某些事務隔離級別讀取數據等操作。 一致性讀(Consistent Nonlocking Reads)會忽略在讀取視圖上的記錄的任何鎖。(舊版本的記錄不能被鎖定;它們通過應用撤銷日志在記錄的內存副本上時被重建。)
所有被共享鎖和排他鎖查詢所設置的鎖都會在事務提交或者回滾之后被釋放。
注:
-
使用 SELECT FOR UPDATE 為 update 操作鎖定行,只適用于 autocommit 被禁用(當使用 START TRANSACTION 開始事務或者設置 autocommit 為0時)。
-
如果 autocommit 已啟用,符合規范的行不會被鎖定。
事務隔離級別
默認的 RR
mysql> show variables like '%iso%'; +-----------------------+-----------------+ | Variable_name | Value | +-----------------------+-----------------+ | transaction_isolation | REPEATABLE-READ | +-----------------------+-----------------+ 1 row in setmysql>共享鎖 VS 排他鎖的區別
-
SELECT … LOCK IN SHARE MODE :共享鎖(S鎖, share locks)。其他事務可以讀取數據,但不能對該數據進行修改,直到所有的共享鎖被釋放。
如果事務對某行數據加上共享鎖之后,可進行讀寫操作;其他事務可以對該數據加共享鎖,但不能加排他鎖,且只能讀數據,不能修改數據。
-
SELECT … FOR UPDATE:排他鎖(X鎖, exclusive locks)。如果事務對數據加上排他鎖之后,則其他事務不能對該數據加任何的鎖。獲取排他鎖的事務既能讀取數據,也能修改數據。
普通 select 語句默認不加鎖,而CUD操作默認加排他鎖。
SELECT … FOR UPDATE 排它鎖 演示
對所在行加上了一把排它鎖 x鎖
【實驗步驟】
| begin 模擬開啟事務 | |
| select * from country where countrycode = ‘CN’ for update ; --讀取成功,但未提交事務 | |
| begin 模擬開啟事務 | |
| select * from country where countrycode = ‘CN’ for update ; ---- 可以讀取成功 | |
| update country set countryname=‘新中國’ where countrycode = ‘CN’; ---- 一直被阻塞,如果會話一一直沒提交,session2 直到超時,拋出如下異常 1205 - Lock wait timeout exceeded; try restarting transaction |
【結論】
通過上述實驗 ,我們可以推斷出其他session只能讀該行數據,修改則會被阻塞,直到鎖定行的session提交事務
SELECT … LOCK IN SHARE MODE 共享鎖 演示
| begin 模擬開啟事務 | |
| select * from country where countrycode = ‘CN’ lock in share mode ; --讀取成功,但未提交事務 | |
| begin 模擬開啟事務 | |
| select * from country where countrycode = ‘CN’ lock in share mode ; ---- 可以加共享鎖 | |
| select * from country where countrycode = ‘CN’ for update ; ---- 不能加排它鎖 一直被阻塞, | |
| update country set countryname=‘China’ where countrycode = ‘CN’ ; — 修改該行數據也被阻塞,如果事務一還沒提交,一直等到超時 1205 - Lock wait timeout exceeded; try restarting transaction |
搞定MySQL
總結
以上是生活随笔為你收集整理的MySQL - 共享锁和排它锁初探的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL - 无索引行锁升级为表锁
- 下一篇: MySQL - 索引优化案例实操