以前在上文已經記錄過鎖的簡單應用今天更深刻的瞭解一下MySQL中的鎖。php
鎖類型 | 存儲引擎 | 特色 |
---|---|---|
表級鎖 | MyISAM、MEMORY、InnoDB(非默認) | 開銷小,加鎖快,不會死鎖,顆粒大,併發低。 |
行級鎖 | InnoDB | 開銷大,加鎖慢,會死鎖,顆粒小,併發高。 |
頁面鎖 | BDB | 介於以上兩種之間,會死鎖。 |
表級鎖支持兩種模式,共享讀鎖和獨佔寫鎖。sql
READ鎖定後,當前線程不能夠寫入,其餘線程寫入會被阻塞到解鎖後執行,查詢不受影響。併發
WRITE鎖定後,當前線程能夠插入查詢,其餘進行插入查詢會被阻塞到解鎖後執行。spa
查看錶等待數量.net
//查看錶等待次數 show status like 'table%';
通常會體如今 table_locks_waited中,若是比較高說明發生大量鎖等待。線程
MySQL執行讀寫操做會自動進行鎖定,通常不須要顯示指定。code
鎖的使用方法能夠參考:鎖的簡單應用blog
LOCK TABLES table_name READ LOCAL;
LOCAL表示容許獲取讀鎖的時候在表結尾進行併發插入。索引
MySQL能夠經過 concurrent_insert 來控制併發插入。進程
concurrent_insert 爲 0 的時候不容許併發插入。
concurrent_insert 爲1 的時候,若是表中不存在空洞能夠在結尾插入。
concurrent_insert 爲 2 的時候,是否有空洞都容許結尾插入。
若是加鎖的時候已經被其餘線程鎖定,則會阻塞到其餘線程解鎖。
若是兩個進程同時進行讀鎖和寫鎖的請求,那麼寫鎖會優先執行,哪怕讀鎖先到。
咱們能夠經過 low-priorty-updates 參數來設置優先級別。
SET LOW_PRIORITY_UPDATES=1; SET LOW_PRIORITY_INSERT=1; SET LOW_PRIORITY_DELETE=1;
經過設置來下降寫的優先級。
同時還能夠經過設置 max_write_lock_count 來實現鎖等待超過必定數量後讀優先,用於避免大量寫操做致使查詢阻塞。
事務做爲一個單獨的處理單元具備原子性,要麼所有執行,要麼所有不執行
事務的開始和結束都保持一致狀態,事務結束的時候必須保證數據是正確的。
併發事務的狀況下,不容許互相影響,每一個事務必須是隔離開的。
事務一旦提交便永久生效。
兩個併發事務A和B,A和B同時讀取了數據,A修改數據提交後,B頁修改數據進行提交,會覆蓋A種修改的數據。
兩個併發事務A和B,A讀取並修改了數據可是沒有提交,B此時讀取了A修改後的數據並提交,此時A回滾了數據,那麼B提交的數據會成爲髒數據。
一個事務讀取數據後,再次讀取數據(同一條數據)發現兩次數據不一致。
一個事務讀取數據後,再次讀取數據(相同條件讀取的數據),發現其餘事務插入了知足條件的新數據。
經過排他鎖避免更新丟失。
這個級別的事務能夠讀取到其餘事務的未提交數據,因此會產生髒讀。
經過排他鎖和共享空間鎖來避免更新丟失和髒讀。
這個級別的事務能夠讀取到其餘事務已經提交的數據,因此屢次讀取會出現「不可重複讀」。
經過排他鎖和共享空間鎖來避免更新丟失和髒讀,在進行讀鎖的時候禁止寫鎖執行,寫鎖的時候禁止任何鎖執行,用於避免重複讀。
最爲嚴格的隔離機制,經過串行的方式保證事務一個一個執行。
//查看隔離級別 select @@global.tx_isolation,@@tx_isolation;
show status like 'innodb_row_lock%';
經過查看返回結果中 鎖等待次數和平均等待時間來判斷當前鎖情況,若是比較高說明當前鎖競爭嚴重,能夠經過查看 schema.innodb_locks來進一步查詢。
共享鎖(S):對一行數據開啓共享鎖,會阻止其餘數據對這行數據開啓排他鎖。
排他鎖(X):得到排他鎖的數據能夠寫數據,其餘數據不能夠得到共享鎖或排他鎖。
爲了兼容表級鎖,實現瞭如下兩種鎖。
意向共享鎖(IS):事務獲得共享鎖以前先取得該鎖。
意向排他鎖(IX):事務獲得排他鎖以前先取得該鎖。
InnoDB種不須要顯式的加鎖,會在執行語句時候自動加鎖解鎖。
InnoDB行鎖經過給索引上的索引項加鎖,沒有索引會加載彙集索引上。
一、Record lock:直接對索引項加鎖
二、Gap lock:對索引項第一條和最後一條的位置加鎖(GAP鎖)用於防止幻讀(RC、RR隔離級別)。
三、Next-key lock:二者結合
InnoDB加鎖若是使用索引(非主鍵),會同時給索引項和彙集索引項加鎖。
範圍查詢的時候會鎖住範圍內的全部索引項。
注意:若是檢索數據沒有經過索引條件檢索(全表掃描),那麼將對錶中全部數據加鎖。