我們首先需要知道的乙個大前提是:mysql的鎖是由具體的儲存引擎實現的。所以像mysql的預設引擎myisam和第三方外掛程式引擎 innodb的鎖實現機制是有區別的。可根據不同的場景選用不同的鎖定機制。
mysql有三種級別的鎖定:表級鎖定、頁級鎖定、行級鎖定
一、定義
每次鎖定的是一張表的鎖機制就是表級別鎖定(table-level)。它是mysql各儲存引擎中粒度最大的鎖定機制。
二、優缺點
1. 優點
實現邏輯簡單,開銷小。
獲取鎖和釋放鎖的速度快。
由於表級鎖一次會將整個表鎖定,所以能很好的避免死鎖問題。
2. 缺點
由於鎖粒度最大,因此出現爭用被鎖定資源的概率也會最高,致使併發度十分低下。
三、支援儲存引擎
使用表級鎖定的主要有myisam,memory,csv等一些非事務性儲存引擎。
四、表級鎖型別
mysql的表級鎖有兩種型別:表共享讀鎖(table read lock)和表獨佔寫鎖(table write lock)。
鎖模式的相容性:
對myisam表的讀操作,不會阻塞其他使用者對同一表的讀請求,但會阻塞對同一表的寫操作;
對myisam表的寫操作,則會阻塞其他使用者對同一表的讀和寫操作;
myisam表的讀操作與寫操作之間,以及寫操作之間是序列的。當乙個執行緒獲得對乙個表的寫鎖後,只有持有鎖的執行緒可以對錶進行更新操作。其他執行緒的讀、寫操作都會等待,直到鎖被釋放為止。
五、如何加表鎖
在執行查詢語句(select)前,會自動給涉及的所有表加讀鎖
在執行更新操作(update、delete、insert等)前,會自動給涉及的表加寫鎖。這個過程並不需要使用者干預,因此不需要直接用lock table命令給myisam表顯式加鎖。
顯示加寫鎖:
// 當乙個執行緒獲得對乙個表的寫鎖後,只有持有鎖的執行緒可以對錶進行更新操作。
// 其他執行緒的讀、寫操作都會等待,直到鎖被釋放為止。
// test表將會被鎖住,另乙個執行緒執行select * from test where id = 3;將會一直等待,直到test表解鎖
lock table test write;
顯示加讀鎖
// test表將會被鎖住,另乙個執行緒執行select * from test where id = 3;不會等待
// 執行update test set name='peter' where id = 4;將會一直等侍,直到test表解鎖
lock table test read;
顯示釋放鎖:
unlock tables;
需要注意的是,在同乙個sql session裡,如果已經獲取了乙個表的鎖定,則對沒有鎖的表不能進行任何操作,否則會報錯。
// 鎖定test表
lock table test write;
// 操作鎖定表沒問題
select * from test where id = 4;
// 操作沒有鎖的表會報錯
select * from bas_farm where id =1356
報錯:[err] 1100 - table 'bas_farm' was not locked with lock tables。這是因為myisam希望一次獲得sql語句所需要的全部鎖。這也正是myisam表不會出現死鎖的原因。
當然,你也不必擔心,myisam引擎的預設方式是會給同乙個session裡的所有表都加上鎖的,不會麻煩你自己顯示操作的。
六、檢視表級鎖爭用情況
執行:show status like 『table%』;
mysql> show status like 'table%';
| variable_name | value |
| table_locks_immediate | 20708 |
| table_locks_waited | 0 |
table_locks_immediate:產生表級鎖定的次數;
table_locks_waited:出現表級鎖定爭用而發生等待的次數;
如果table_locks_waited狀態值比較高,那麼說明系統中表級鎖定爭用現象比較嚴重,就需要進一步分析為什麼會有較多的鎖定資源爭用了。
七、優化表級鎖定
優化表級鎖時的最大問題是:提高併發度
###1. 通過減少查詢時間縮短鎖定時間
縮短鎖定時間的總體原則是:讓query執行時間盡可能的短。
儘量減少大的、複雜的query,將複雜query分拆成幾個小的query分步執行;
盡可能的建立足夠高效的索引,讓資料檢索更迅速;
盡量讓myisam儲存引擎的表只存放必要的資訊,控制字段型別;
利用合適的機會優化myisam表資料檔案。
###2. 設定可併發插入:concurrent_insert=2
myisam的表鎖雖是讀寫互相阻塞的,但依然能夠實現並行操作。myisam儲存引擎有乙個控制是否開啟concurrent insert(併發插入)功能的引數選項:concurrent_insert,取值範圍為0,1,2。
concurrent_insert=0,不允許併發插入。
concurrent_insert=1,如果myisam表中沒有空洞(即表的中間沒有被刪除的行),myisam允許在乙個執行緒讀表的同時,另乙個執行緒從表尾插入記錄。這是mysql的預設設定;
concurrent_insert=2,無論myisam表中有沒有空洞,都允許在表尾併發插入記錄;
所以,我們可通過設定concurrent_insert=2,同時定期在系統空閒時段執行optimize table tablename語句來整理空間碎片,收回因刪除記錄而沒有真正釋放的空間,從而提高併發。optimize參考:mysql中optimize table的作用及使用
###3. 合理設定讀寫優先順序
myisam儲存引擎預設是寫優先順序大於讀優先順序。即使是寫請求後到,寫鎖也會插到讀鎖請求之前。
update low_priority article set click_num=134 where id = 823
low_priority使得系統認為update操作優化級比讀操作低,如果同時出現讀操作和上面的更新操作,則優先執行讀操作。
mysql提供了幾個語句調節符,允許你修改它的排程策略:
low_priority關鍵字應用於:delete、insert、load data、replace和update。
high_priority關鍵字應用於:select、insert語句。
delayed(延遲)關鍵字應用於:insert、replace語句。
如果你希望所有支援low_priority選項的語句都預設地按照低優先順序來處理,那麼可能使用**low-priority-updates**選項來啟動伺服器。然後可通過使用insert high_priority table.....來把個別我們希望的insert語句提高到正常的寫入優先順序。
MySQL行級鎖 表級鎖
行級鎖 表級鎖的資料不能被其它事務再鎖定,也不被其它事務修改 修改 刪除 是表級鎖時,不管是否查詢到記錄,都會鎖定表 innodb 行鎖是通過給索引上的索引項加鎖 來實現的,這一點mysql與 oracle 不同,後者是通過在資料塊中對相應資料行加鎖來實現的。innodb這種行鎖實現特點意味著 只有...
mysql的行級鎖 表級鎖 頁級鎖
鎖是在執行多執行緒時用於強行限制資源訪問的同步機制,即用於在併發控制中保證對互斥要求的滿足 行級鎖 是mysql中鎖定粒度最細的一種鎖,表示只針對當前操作的行進行加鎖。行級鎖能大大減少資料庫操作的衝突。其加鎖粒度最小,但加鎖的開銷也最大。行級鎖分為共享鎖和排他鎖 特點 開銷大,加鎖慢,會出現死鎖 鎖...
mysql 讀寫鎖 表鎖myisam
讀鎖 session1 lock table book read unlock tables session1可以讀book 不可以寫book 也不可以讀寫其它表 session2可以讀book 也可以讀寫其它表 可以寫book 但阻塞的需要session1解鎖後unlock tables 寫鎖 s...