描述
兩階段鎖協議
行鎖是在需要的時候才加上的,但並不是不需要了就立刻釋放,而是要等到事務結束時才釋放
行鎖針對資料表中行記錄的鎖
死鎖當併發系統中不同執行緒出現迴圈資源依賴,涉及的執行緒都在等待別的執行緒釋放資源時,就會導致這幾個執行緒都進入無限等待的狀態
根據加鎖的範圍,mysql 裡面的鎖大致可以分成全域性鎖、表級鎖和行鎖三類
全域性鎖就是對整個資料庫例項加鎖, mysql 提供了乙個加全域性讀鎖的方法,
命令是 flush tables with read lock (ftwrl)。當你需要讓整個庫處於唯讀狀態的時候,
可以使用這個命令,之後其他執行緒的以下語句會被阻塞:資料更新語句(資料的增刪改)、資料定義語句(包括建表、修改表結構等)和更新類事務的提交語句。
全域性鎖使用場景: 全庫邏輯備份。
mysql 裡面表級別的鎖有兩種:一種是表鎖,一種是元資料鎖(meta data lock,
mdl)。
表鎖的語法是lock tables … read/write
解鎖的語法是unlock tables, 也可以在客戶端斷開的時候自動釋放
舉個例子, 如果在某個執行緒 a 中執行 lock tables t1 read, t2 write;這個語句,則其他執行緒寫 t1、讀寫 t2 的語句都會被阻塞。同時,執行緒 a 在執行 unlock tables之前,也只能執行讀t1、讀寫t2的操作。連寫t1都不允許,自然也不能訪問其他表。
另乙個表級鎖是mdl,元資料鎖,這個鎖在訪問乙個表時自動進行加上,防止讀寫不正確。
修改表導致資料庫掛掉
我們可以看到 session a 先啟動,這時候會對錶 t 加乙個 mdl 讀鎖。由於 session b 需要的也是 mdl 讀鎖,因此可以正常執行。
之後 session c 會被 blocked,是因為 session a 的 mdl 讀鎖還沒有釋放,而 session c 需要 mdl 寫鎖,因此只能被阻塞。
如果只有 session c 自己被阻塞還沒什麼關係,但是之後所有要在表 t 上新申請 mdl 讀鎖的請求也會被session c阻塞。前面我們說了,所有對錶的增刪改查操作都需要先申請mdl 讀鎖,就都被鎖住,等於這個表現在完全不可讀寫了。
所以,mdl在語句執行開始的時候申請,語句結束後並不會馬上釋放,會等到整個事務提交之後再釋放。
如何安全給小表加字段
首先解決掉上事務,事務不提交,就會一直佔著mdl鎖,在mysql的
information_schema
庫的innodb_trx表中,你可以查到當前執行中的事務。如果你要做 ddl變更的表剛好有長事務在執行,要考慮先暫停 ddl,或者 kill 掉這個長事務。
對於請求頻繁的表,可以在alter table時設定等待時間,等待時間內沒有獲取到鎖就放棄,不讓它阻塞後面的業務語句。
如
alter
table tbl_name nowait add
column..
.alter
table tbl_name wait n add
column..
.
mysql 的行鎖是在引擎層由各個引擎自己實現的。但並不是所有的引擎都支援行鎖比
如 myisam 引擎就不支援行鎖。不支援行鎖意味著併發控制只能使用表鎖,對於這種引
擎的表,同一張表上任何時刻只能有乙個更新在執行,這就會影響到業務併發度。innodb是支援行鎖的,這也是 myisam 被 innodb 替代的重要原因之一。
行鎖:是針對資料表中行記錄的鎖。假如事務a更新一行資料,事務b也要更新一行資料,那麼事務b必須等待事務a執行完畢後才能更新。如下圖所示:
事務a在執行更新語句後,事務b將會堵塞,直到事務a進行commit之後,事務b才會繼續執行。
在 innodb 事務中,行鎖是在需要的時候才加上的,但並不是不需要了就立刻
釋放,而是要等到事務結束時才釋放。這個就是兩階段鎖協議。
所以,如果你的事務中需要鎖多個行,要把最可能造成鎖衝突、最可能影響併發度的鎖盡量往後放
當併發系統中不同執行緒出現迴圈資源依賴,涉及的執行緒都在等待別的執行緒釋放資源時,就會導致這幾個執行緒都進入無限等待的狀態,稱為死鎖,如下圖所示
死鎖出現後的兩種策略:
直接進入等待,直到超時。這個超時時間可以通過引數innodb_lock_wait_timeout
來設定。
發起死鎖檢測,發現死鎖後,主動回滾死鎖鏈條中的某乙個事務,讓其他事務得以繼續執行。將引數innodb_deadlock_detect
設定為 on,表示開啟這個邏輯。
在innodb中,innodb_lock_wait_timeout
的預設值是 50s
MySQL 全域性鎖 表鎖以及行鎖
mysql 5.7.25 ubuntu 16.04 全域性鎖即對整個資料庫例項加鎖,使得整個庫處於唯讀狀態,會阻塞dml和ddl語句。使用如下命令 簡稱ftwrl 可為資料庫加全域性鎖 flush tables with read lock 釋放全域性鎖命令如下 unlock tables 此外,在...
《MySQL必懂系列》全域性鎖 表級鎖 行鎖
mysql提供了不同等級的鎖,按限制能力的劃分,分為全域性鎖 表鎖 行鎖。本文會描述不同鎖的應用場景與實現原理。全域性鎖就是對整個mysql資料庫加鎖,mysql中的命令是 flush tables with read lock ftwrl 在執行這個命令之後,mysql進入全域性鎖的狀態,整個資料...
MySQL行級鎖 表級鎖
行級鎖 表級鎖的資料不能被其它事務再鎖定,也不被其它事務修改 修改 刪除 是表級鎖時,不管是否查詢到記錄,都會鎖定表 innodb 行鎖是通過給索引上的索引項加鎖 來實現的,這一點mysql與 oracle 不同,後者是通過在資料塊中對相應資料行加鎖來實現的。innodb這種行鎖實現特點意味著 只有...