目錄
事務
MySQL事務的四大特性
ACID
原子性
持久性
隔離性
事務的隔離級別
讀未提交
讀已提交
可重復讀
串行化
事務的隔離級別如何實現
MVCC
版本鏈
READVIEW
高可用
MySQL數據庫的讀寫分離
主從復制
主從同步延遲怎么處理
分庫策略
水平分庫分表的策略
事務
MySQL事務的四大特性
事務是一條或多條 SQL 語句組成的執行單元。四個特性分別是原子性、一致性、隔離性和持久性。原子性保證事務中的操作要么全部執行、要么全部失敗;一致性保證數據從事務開始前的一個一致狀態轉移到結束后的另外一個一致狀態;隔離性保證并發事務之間互不干擾;持久性保證事務提交后數據不會丟失。
ACID
就是事務的四大特性
原子性
ACID 中的原子性主要通過 Undo Log 來實現,持久性通過 Redo Log 來實現,隔離性由 MVCC 和鎖機制來實現,一致性則由其他三大特性共同保證。
事務對數據進行修改前,會記錄一份快照到 Undo Log,如果事務中有任何一步執行失敗,系統會讀取 Undo Log 將所有操作回滾,恢復到事務開始前的狀態,從而保證事務要么全部成功,要么全部失敗。
持久性
MySQL 的持久性主要由預寫 Redo Log、雙寫機制、兩階段提交以及 Checkpoint 刷盤機制共同保證。
當事務提交時,MySQL 會先將事務的修改操作寫入 Redo Log,并強制刷盤,然后再將內存中的數據頁刷入磁盤。這樣即使系統崩潰,重啟后也能通過 Redo Log 重放恢復數據。
隔離性
主要通過鎖機制和 MVCC 來實現。
比如說一個事務正在修改某條數據時,MySQL 會通過臨鍵鎖來防止其他事務同時進行修改,避免數據沖突
MySQL默認事務自動提交
事務的隔離級別
MySQL 支持四種隔離級別,分別是:讀未提交、讀已提交、可重復讀和串行化。
讀未提交
事務可以讀取其他未提交事務修改的數據。也就是說,如果未提交的事務一旦回滾,讀取到的數據就會變成了“臟數據”,通常不會使用。
讀已提交
讀已提交避免了臟讀,但可能會出現不可重復讀,即同一事務內多次讀取同一數據結果會不同,因為其他事務提交的修改,對當前事務是可見的。
可重復讀
可重復讀能確保同一事務內多次讀取相同數據的結果一致,即使其他事務已提交修改。
串行化
串行化是最高的隔離級別,通過強制事務串行執行來解決“幻讀”問題。
事務的隔離級別如何實現
讀未提交通過行鎖共享鎖確保一個事務在更新行數據但沒有提交的情況下,其他事務不能更新該行數據,但不會阻止臟讀,意味著事務2 可以在事務1 提交之前讀取到事務1 修改的數據
讀已提交會在更新數據前加行級排他鎖,不允許其他事務寫入或者讀取未提交的數據,也就意味著事務2 不能在事務 1 提交之前讀取到事務1 修改的數據,從而解決臟讀的問題。
可重復讀只在第一次讀操作時生成 ReadView,后續讀操作都會使用這個 ReadView,從而避免不可重復讀的問題。
另外,對于當前讀操作,可重復讀會通過臨鍵鎖來鎖住當前行和前間隙,防止其他事務在這個范圍內插入數據,從而避免幻讀的問題。
MVCC
多版本并發控制
每次修改數據時,都會生成一個新的版本,而不是直接在原有數據上進行修改。并且每個事務只能看到在它開始之前已經提交的數據版本。
其底層實現主要依賴于 Undo Log 和 Read View。
版本鏈
版本鏈是指 InnoDB 中同一條記錄的多個歷史版本,通過 DB_ROLL_PTR 字段將它們像鏈表一樣串起來,用來支持 MVCC 的快照讀。
READVIEW
ReadView 是 InnoDB 為每個事務創建的一份“可見性視圖”,用于判斷在執行快照讀時,哪些數據版本是當前這個事務可以看到的,哪些不能看到。
高可用
MySQL數據庫的讀寫分離
讀寫分離就是把“寫操作”交給主庫處理,“讀操作”分給多個從庫處理,從而提升系統并發性能。
應用層通過中間件(如 MyCat、ShardingSphere)自動路由請求,將 INSERT / UPDATE / DELETE 等寫操作發送給主庫,將 SELECT 查詢操作發送給從庫。
主從復制
MySQL 的主從復制是一種數據同步機制,用于將數據從主數據庫復制到一個或多個從數據庫。
主庫執行事務提交時,將數據變更以事件形式記錄到 Binlog。從庫通過 I/O 線程從主庫的 Binlog 中讀取變更事件,并將這些事件寫入到本地的中繼日志文件中,SQL 線程會實時監控中繼日志的內容,按順序讀取并執行這些事件,從而保證從庫與主庫數據一致。
主從同步延遲怎么處理
主從同步延遲是因為從庫需要先接收 binlog,再執行 SQL 才能同步主庫數據,在高并發寫或網絡抖動時容易出現延遲,導致讀寫不一致。
第一種解決方案:對一致性要求高的查詢(如支付結果查詢)可以直接走主庫。
第二種解決方案:對于非關鍵業務允許短暫數據不一致,可以提示用戶“數據同步中,請稍后刷新”,然后借助異步通知機制替代實時查詢。
第三種解決方案:采用半同步復制,主庫在事務提交時,要等至少一個從庫確認收到 binlog(但不要求執行完成),才算提交成功。
分庫策略
分庫的策略有兩種,第一種是垂直分庫:按照業務模塊將不同的表拆分到不同的庫中,比如說用戶、登錄、權限等表放在用戶庫中,商品、分類、庫存放在商品庫中,優惠券、滿減、秒殺放在活動庫中。
第二種是水平分庫:按照一定的策略將一個表中的數據拆分到多個庫中,比如哈希分片和范圍分片,對用戶 id 進行取模運算或者范圍劃分,將數據分散到不同的庫中。
水平分庫分表的策略
常見的分片策略有三種,范圍分片、Hash 分片和路由分片。
范圍分片是根據某個字段的值范圍進行水平拆分。適用于分片鍵具有連續性的場景
Hash 分片是指通過對分片鍵的值進行哈希取模,將數據均勻分布到多個庫表中,適用于分片鍵具有離散性的場景。
路由分片是通過路由配置來確定數據應該存儲在哪個庫表,適用于分片鍵不規律的場景。