MySql高性能筆記 - (一)Mysql基礎知識
1. 讀寫鎖:###
- 讀鎖 - 共享鎖:互相不阻塞的。多個客戶在同一刻可以同時讀取同一個資源,而互不干擾。
- 寫鎖 - 排它鎖:一個寫鎖會阻塞其他的寫鎖和讀鎖,保證只有一個用戶能執行寫操作,防止其他用戶讀取正在寫入的同一資源。
2. 鎖粒度:##
- 盡量只鎖定要修改的部分數據。
- 表鎖:開銷小,它會鎖定整張表。
- 行級鎖:可以最大程度的支持并發處理,同時帶來最大的鎖開銷。行級鎖是在存儲引擎層實現的,InnoDB和XtraDB實現了行級鎖,
3. 死鎖:
- 發生舉例:
- 第一條sql進行update A行數據,鎖定了A行數據,嘗試去執行update B行數據。
- 第二條sql進行update B行數據,鎖定了B行數據,嘗試去執行update A行數據。
- 解決方案:
- InnoDB會提前檢測死鎖循環依賴,返回錯誤。發生以后目前處理方法是,將持有最少行級排他鎖的事務進行回滾。
4. 事務:
事務是一組原子性的sql語句,如果數據庫成功地執行所有語句,那么久執行。如果一條語句崩潰,那就所有語句都不會執行。要么全執行,要么全失敗。
-
ACID:原子性(atomicity)、一致性(consistency)、隔離性(isolation)、持久性(durability)
- 原子性:一個事務必須視為一個不可再分的最小工作單元。整個事務要么都提交成功,要么都失敗回滾。
- 一致性:數據庫總是從一個一致性狀態轉換到另一個一致性狀態。
- 隔離性:一個事務在最終提交之前,對其他事務是不可見的。
- 持久性:一旦事務提交,講永久保存在數據庫中。及時系統崩潰,也不會丟失。
-
Mysql默認采用自動提交事務模式 autocommit。
`show variables like 'autocommit'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | autocommit | ON | +---------------+-------+ 1 行于數據集 (0.04 秒) `
5.隔離級別:
- Read Uncommitted(未提交讀):事務中的修改,及時沒有提交,對其他事務也是課件的。其他事務可以讀取未提交的數據,成為臟讀。一般很少使用。
- Read Committed(提交讀)(不可重復讀):事務的修改,在提交之前對其他事務都不可見。會導致A事務在修改一行數據之前,B 輸入做過讀??;A事務提交成功以后,B事務在讀取引起不一樣的結果。
- Repeatable Read(可重復讀):解決在同一事務多次讀取同樣記錄的結果一致,讀取的數據在本事務內防止其他事務對其修改。但是防止不了此時做新增,引起幻讀幻讀問題。InnoDB和XtraDB通過版本并發控制MVCC,解決幻讀問題。Mysql默認隔離級別。
- Serializable(可串行化):最高的隔離級別。通過強制的事務串行執行,避免幻讀問題。在讀取每一行數據上都加鎖,導致大量的鎖征用問題。
Innodb對四種類型都支持,臟讀和串行化應用場景不多,讀提交、重復讀用的比較廣泛。
隔離級別 | 臟讀可能性 | 不可重復讀可能性 | 幻讀可能性 | 加鎖讀 |
---|---|---|---|---|
Read Uncommitted | Yes | Yes | Yes | No |
Read Committed | No | Yes | Yes | No |
Repeatable Read | No | No | Yes | No |
Serializable | No | No | No | Yes |
6. 版本并發控制MVCC
可以認為MVCC是行級鎖的一個變種,但是他避免了很多情況的加鎖操作,降低開銷。實現了非阻塞的讀操作,和寫操作的鎖定必要行。MVCC的實現是通過保存數據在某個時間點的快照實現的。分為樂觀并發控制、悲觀并發控制。
InnoDB的MVCC是通過在沒行記錄后面保存三個隱藏的列。
- DB_TRX_ID:6byte的標識,每處理一個事務,就自動+1.
- DB_ROLL_PTR:7byte的標識,一條undo log記錄,記錄操作前的ROW值。
- DB_ROW_ID:6byte,若沒有主鍵才會有。
- select操作:
- 對于select的操作,只有同時滿足如下2個條件才返回行記錄
- 行的修改版本號小于等于該事務版本號
- 行的刪除版本號要么沒有被定義,要么大于事務版本號。
- 如果行的修改或者刪除版本號大于事務號,說明行是被修改事務后啟動的事務修改或者刪除的。在可重復讀的隔離級別下,后開始的事務堆數據的影響不應該被先開始的事務看見,所以應該忽略后開始的事務的更新或者刪除操作。
- insert操作:
新插入的行,行的修改版本號為更新為該事務的事務號。 - update操作:
更新行的時候,InnoDB會把原來行復制一份,并把當前的事務號作為改行的修改版本號。把原來的記錄標記為已刪除版本號是事務版本號。 - delete操作:
對于刪除,InnoDB直接把改行的刪除版本號修改為當前事務號,相當于標記為刪除,而不是物理的刪除。真是的刪除是在InnoDB的purge線程去做的。