mysql筆記(一)

1. Mysql架構

1.1 架構圖

image

1.2 讀寫鎖

共享鎖:讀鎖

多個用戶同一時刻可以同時讀取同一個資源互不干擾

排他鎖:寫鎖

寫鎖會阻塞其他的寫鎖和讀鎖

1.3 鎖粒度

表級鎖

  1. 開銷最小的鎖策略
  2. 對整張表加鎖

獲取表級寫鎖會阻塞其他用戶對該表的所有讀寫操作,讀鎖之間是不互相阻塞的

寫鎖比讀鎖具有更高的優先級,寫鎖請求可能會插入到讀鎖隊列前

除儲存引擎,Mysql本身也可以使用有效的表鎖來實現不同的目的

行級鎖

  1. 帶來最大的鎖開銷
  2. 可以最大程度支持併發處理

行級鎖只在儲存引擎(InnoDB 和 XtraDB)層實現,Mysql服務器層沒有實現

1.4 事務

  1. 事務內的語句,要麼全部執行成功,要麼全部執行失敗。支持事務的系統要通過嚴格的ACID測試。
  2. 對於不需要事務的業務場景,用戶可以選擇一個非事務型的存儲引擎,來獲得更高的性能,當然即使存儲引擎不支持事務,Mysql服務器的表級鎖也可以提供一定程度的保護。

原子性(atomicity)

一個事務必須被視爲一個不可分割的最小執行單元,要麼全部提交成功,要麼全部失敗回滾,不能只執行其中的一部分。

一致性(consistency)

數據庫總是從一個一致性狀態轉換到另一個一致性狀態,除非事務最終提交,不然事務的修改不會提交到數據庫中。

隔離性(isolation)

一個事務在最總提交前,通常對其他事務不可見,如事務a過程中對賬號金額200進行了修改,但是事務a還未提交,這時事務b看到的賬號金額還是是未修改的200。

持久性(durability)

一旦事務提交,其所做修改會永久保存在數據庫中。

1.5 隔離級別

每種存儲引擎實現的隔離級別不盡相同

READ UNCOMMITTED(未提交讀)

  • 事務中的修改,即使沒有提交,對其他事務也都是可見的。
  • 事務可以讀取到未提交的數據,這也稱爲髒讀(Dirty Read)。
  • 除非真的有非常必要的理由,在實際應用中一般很少使用。

READ COMMITTED(提交讀)

  • 大多數數據庫系統的默認隔離級別(Mysql不是0)。
  • 一個事務只能“看見”已經提交的事務所做的修改。一個事務從開始直到提交之前,所做的修改對其他事務不可見。但是可能出現一個事務中兩次執行同樣查詢時,得到結果不一樣的情況。
  • 該級別也叫不可重複讀(nonrepeatable read)。

不可重複讀,例如:

  • 事務A:
select money from user where account = "123";

結果:2000

  • 事務B:
update user set money = 3000 where account = "123";

事務B提交

  • 事務A:
select money from user where account = "123";

結果: 3000
事務A提交

事務A過程中出現了前後查詢讀取到的數據不一致的問題,所以該級別被稱作不可重複讀。

REPEATABLE READ(可重複讀)

  • 該級別保證了同一事務中多次讀取同樣記錄的結果是一致的。
  • 該級別是Mysql的默認事務級別。但是理論上,該級別還是無法解決另一個幻讀(Phantom Read)問題。
  • 幻讀(Phantom Read)指某個事務在讀取某個範圍內的記錄時,另一個事務又在該範圍內插入了新的記錄,當之前的事務再次讀取某個該範圍的記錄時,就會產生環行。
  • InnoDB和XtraDB存儲引擎通過多版本併發控制(MVCC, Multiversion Concurrency Control)解決幻讀問題。

幻讀,例如:

  • 事務A:
select * from user;

結果有10行

  • 事務B:
Insert into user value(11,"asd");

事務B提交

  • 事務A:
select * from user;

結果有11行

此時就出現了幻讀,兩次讀取結果行數不一致。

SERIALIZABLE(可串行化)

  • 最高隔離級別。
  • 通過強制事務串行執行避免幻讀,簡單說就是在讀取的每一行數據上都加鎖,可能導致大量超市和鎖爭用的問題。
  • 實際很少使用,除非要非常需要確保數據的一致性而且可以接受沒有併發的情況下。

隔離級別圖表

image

1.6 死鎖

當多個事務視圖以不同的順序鎖定資源時,就可能會產生死鎖。例如,設想下面兩個事務同時處理StockPrice表:

事務1:

START TRANSACTION;
UPDATE StockPrice SET close = 45.50 WHERE stock_id = 4 and date = '2002-05-01';
UPDATE StockPrice SET close = 19.80 WHERE stock_id = 3 and date = '2002-05-02';
COMMIT;

事務2:

START TRANSACTION;
UPDATE StockPrice SET close = 45.50 WHERE stock_id = 3 and date = '2002-05-01';
UPDATE StockPrice SET close = 19.80 WHERE stock_id = 4 and date = '2002-05-02';

如果湊巧,兩個事務都執行了第一條UPDATE語句,同時也鎖定了該行數據,接着每個事務都嘗試去執行第二條UPDATE語句,卻發現該行被鎖定了,然後兩個事務都等待對方釋放鎖,同時又持有對方需要的鎖,陷入死循環。

  • 爲了解決這些問題,數據庫系統實現了各種死鎖檢測和死鎖超時機制。
  • InnoDB目前處理死鎖的方法是,將持有最少行級排他鎖的事務進行回滾。

1.7 事務日誌

修改數據流程:
修改數據改內存拷貝 -> 修改事務日誌 -> 持久化事務日誌 -> 內存拷貝持久化

  • 事務日誌可以提升事務的效率。
  • 存儲引擎在修改表的數據時只需要修改其內存拷貝,再把該修改行爲記錄到持久在硬盤上的事務日誌中,而不用每次都將修改的數據本身持久到磁盤上。
  • 事務日誌採取追加方式,寫日誌的操作是在磁盤上的一小塊區域進行順序I/O,不像隨機I/O多次移動磁頭,所以事務日誌效率較高。
  • 事務日誌持久以後,內存中被修改的數據在後臺可以慢慢地刷回到磁盤。
  • 如果修改已經記錄到事務日誌並持久化,但是數據本身並沒有寫回磁盤,此時系統崩潰,存儲引擎在重啓時可以自動恢復這部分修改的數據。

1.8 MySQL中的事務

MySQL提供了兩種事務型的存儲引擎:InnoDB和NDB Cluster,另外還有一些第三方的存儲引擎也支持事務:XtraDB和PBXT。

自動提交(AUTOCOMMIT)

  • Mysql默認採用自動提交,如果不是顯示地開始一個事務,則每個查詢都會被當作一個事務執行提交操作。
  • 當前連接中,可以通過設置AUTOCOMMIT變量來啓用或者禁用自動提交操作。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章