mysql性能優化系列3-鎖和事務

1. 鎖分類

  • 表級鎖:開銷小,加鎖快,不會出現死鎖。鎖定粒度大,發生鎖衝突的概率最高,併發度最低。適合於以查詢爲主,只有少量按索引條件更新數據的應用。
  • 行級鎖:開銷大,加鎖慢,會出現死鎖。鎖定粒度最小,發生鎖衝突的概率最低,併發度也最高。適合於有大量按索引條件併發更新少量不同數據,同時又有併發查詢的應用。
  • 頁面鎖:開銷和加鎖時間界於表鎖和行鎖之間,會出現死鎖。鎖定粒度界於表鎖和行鎖之間,併發度一般。

MyISAM和MEMORY存儲引擎採用的是表級鎖,InnoDB存儲引擎既支持行級鎖(默認)和表級鎖。

2. MyISAM鎖

MyISAM的表級鎖有兩種模式,共享鎖和獨寫鎖。

  • MyISAM表的讀操作,不會阻塞其他會話對同一表的讀請求,但會阻塞對同一表的寫請求
  • MyISAM表的寫操作,則會阻塞其他會話對同一表的讀和寫操作,當前會話可以對本表做CRUD
  • 一個會話使用LOCK TABLE命令給表加了讀鎖,這個會話可以查詢鎖定表中的記錄,但更新或訪問其他表都會提示錯誤

(1)隱式加鎖
MyISAM在執行SELECT操作前,會自動給涉及的所有表加讀鎖,在執行UPDATE、DELETE、INSERT等操作前,會自動給涉及的表加寫鎖。
(2)顯式加鎖

  • 讀鎖:LOCK TABLE 表名 read
  • 寫鎖:LOCK TABLE 表名 write
  • 釋放鎖:unlock tables

concurrent_insert
MyISAM是讀寫互相阻塞,但不是完全串行化,也可以並行。concurrent_insert就是用來控制併發插入的

  • concurrent_insert=2,無論MyISAM表中有沒有空洞(表的中間沒有被刪除的行),都允許在表尾併發插入記錄
  • concurrent_insert=1(默認),如果MyISAM表中沒有空洞,MyISAM允許在一個進程讀表的同時,另一個進程從表尾插入記錄
  • concurrent_insert=0,不允許併發插入

讀寫優先級
寫進程先獲得鎖,即使讀請求先到鎖等待隊列,寫請求後到,寫鎖也會先獲得鎖。因此大量的更新操作會造成查詢操作很難獲得讀鎖,從而可能永遠堵塞。解決方法: set low_priority_updates =1;,使該連接發出的更新請求優先級降低

3. InnoDB鎖

3.1 行鎖和表鎖

(1)行鎖
行鎖分爲共享鎖和排它鎖。

  • 共享鎖:讀鎖。當一個事務對某幾行上讀鎖時,允許其他事務對這幾行進行讀操作,但不允許其進行寫操作
  • 排它鎖:寫鎖。當一個事務對某幾個上寫鎖時,不允許其他事務讀寫

(2)表鎖
意向鎖是一種表級鎖。分爲意向共享鎖(IS)和意向排他鎖(IX)。在給表加行鎖前會先加表鎖。

  • 意向共享鎖(IS):事務給數據行加入共享鎖前必須給該表的加IS鎖。
  • 意向排他鎖(IX):事務給數據行加入排他鎖前必須給該表的加IX鎖。
    在這裏插入圖片描述
    注意
  • 各意向鎖之間不衝突
  • 對於insert、update、delete,InnoDB會自動給涉及的數據加排他鎖,select不會加任何鎖
  • 顯式加鎖:SELECT … LOCK IN SHARE MODE(共享鎖)、SELECT … FOR UPDATE(排他鎖)
  • 意向鎖是InnoDB自動加的,不需要用戶干預
  • 行鎖必須有索引才能實現,否則會自動鎖全表,那麼就不是行鎖了
  • 上述共享鎖和排他鎖在事務中才有效果,普通的select查詢不會加鎖,所以一個會話即使加了排它鎖、另一個會話使用普通select也可以查詢

4. ACID

事務具有4個屬性:原子性、一致性、隔離性、持久性。

  • 原子性(atomicity):事務是一個不可分割的工作單位,事務中所有操作要麼全部成功,要麼都不成功
  • 一致性(consistency):事務必須使數據庫從一個一致性狀態變到另一個一致性狀態,不能有中間態
  • 隔離性(isolation):一個事務的執行不被其他事務干擾
  • 持久性(durability):事務一旦提交,對數據庫的改變就是永久性的

5. 隔離性

隔離性(isolation):事務對數據庫修改,在未提交完成前對於其他事務不可見。
隔離性分爲四種:
(1)未提交讀(READ UNCOMMITED)
有髒讀現象,事務A讀取了事務B更新的數據,然後B回滾操作,那麼A讀取到的數據是髒數據
(2)已提交讀(READ COMMITED)
沒有髒讀,但不可重複讀。事務A在讀取同一數據後,事務B對數據作了更新並提交,然後事務A再次讀取數據,這樣事務A讀取兩次數據,但結果不一致
(3)可重複讀(REPEATABLE READ)
不會有髒讀、不可重複讀。但會有幻讀,一個事務讀取到了另外一個事務insert的數據。
不可重複讀側重於修改,幻讀側重於新增或刪除。解決不可重複讀的問題只需鎖住滿足條件的行,解決幻讀需要鎖表
(4)可串行化(SERIALIZABLE)
可避免髒讀、不可重複讀、幻讀
隔離級別從未提交讀->已提交讀->可重複讀->可串行化,由低到高,級別越高,執行效率越低
事務隔離級別爲可重複讀時,如果以索引列爲條件更新數據,會存在間隙鎖間、行鎖、頁鎖的問題,從而鎖住一些行。如果沒有索引,更新數據時會鎖住整張表。事務隔離級別爲串行化時,讀寫數據都會鎖住整張表。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章