資料庫系列:MySQL慢查詢分析和效能優化
資料庫系列:MySQL索引優化總結(綜合版)
資料庫系列:高並行下的資料欄位變更
資料庫系列:覆蓋索引和規避回表
資料庫系列:資料庫高可用及無失真擴容
資料庫系列:使用高區分度索引列提升效能
資料庫系列:字首索引和索引長度的取捨
資料庫系列:MySQL引擎MyISAM和InnoDB的比較
並行控制是為了防止多使用者並行使用資料庫時造成資料錯誤和程式執行錯誤,保證資料的完整性。當多個事務並行地存取資料庫時,就會產生同時讀取和/或修改同一資料的情況。若對並行操作不加控制就可能會存取和儲存不正確的資料,破壞資料庫的一致性(Consistency)。因此,資料庫中介軟體必須提供並行控制(Concurrency Control)機制能力,而MySQL的InnoDB引擎,很好的支援了這一塊。
MySQL 是一個流行的關係型資料庫管理系統,它支援多使用者並行存取。並行控制是確保資料庫一致性和完整性的重要機制。在 MySQL 中,有幾種方法可以實施並行控制:
通過合理設定和使用上述機制,可以在 MySQL 中實現有效的並行控制,來保證在資料庫中執行一致性和資料完整性。
下面詳細來說說通過並行控制保證資料一致性的常見手段:
MySQL 使用鎖來保持資料的一致性。在並行控制中,鎖是用來防止多個事務同時對同一資料進行修改或刪除,以保持資料的一致性。MySQL 中的鎖機制包括共用鎖和排他鎖。
鎖的基本實現,一般是這樣的:
但是存在一個問題,他的執行本質是序列的,無論讀寫,都無法並行,這樣效能太差了,也不符合網際網路高並行需求。
於是MySQL 中的鎖機制實現了共用鎖和排他鎖:
所以說,單純的鎖機制,還是不滿足需求,為了保證寫任務沒有完成之時,其他讀的任務也可以並行執行,我們就需要使用另外一個能力來補充。
那就是資料多版本(Multi Versioning)
MySQL的並行控制是通過多版本並行控制(MVCC)實現的。MVCC允許在事務隔離級別下執行一致性讀操作,以提高並行效能。
在MySQL的MVCC中,每個資料行都有多個版本,每個版本都表示該行在不同時間點的狀態。當一個事務讀取資料時,它只看到該事務開始之前存在的資料版本,而不是當前最新的資料版本。這種方式允許並行讀取多個資料版本,而不會相互阻塞,進一步提高並行的效果。
詳細拆分開來,讀寫同步執行的原理是這樣的:
如圖所示,可以分成這幾個步驟去解讀:
從這邊可以看出,資料多版本,讀寫之間不需要阻塞,能夠極大提高任務的並行能力。
在MySQL的InnoDB儲存引擎中,使用MVCC(多版本並行控制,Multiversion Concurrency Control)實現多版本控制。
MVCC的實現主要基於undo紀錄檔、redo紀錄檔、rollback segment 回滾儲存區間、和read view。undo紀錄檔用於回滾操作,而read view用於生成資料行的歷史版本。通過這種方式,InnoDB實現了非阻塞的一致性讀操作。
redo紀錄檔
資料庫事務提交後,必須將更新的資料刷到磁碟上,以保證ACID特性。磁碟隨機寫效能較低,且過度頻繁的刷盤,會極大影響資料庫的吞吐量。
優化方式是將修改行為先寫到redo紀錄檔裡,這樣隨機就變成了有序性,再按照時間週期將資料持久化到磁碟上,極大提高了效能。
另外一方面,即使資料庫崩潰,恢復之後也可以從redo紀錄檔裡面獲取操作Log,重新提交事務操作,然後刷盤,最終保證資料的一致性。
undo紀錄檔
資料庫事務未提交時,會將事務修改資料的Mirror Data(修改前的版本 )存放到 Undo Log中,它的主要作用是在事務執行過程中,如果發生錯誤或者需要回滾操作,可以通過Undo Log中的記錄來複原已經執行的操作,恢復資料到事務開始之前的狀態。
另外一方面,資料庫奔潰時,也可以使用undo紀錄檔,復原未提交事務,保證事務的ACID特性。
rollback segment
Rollback Segment(回滾儲存區)是資料庫中的一部分儲存空間,用於臨時儲存當資料庫資料發生改變時的先前值。它主要有兩個作用:
# 表結構
t_userinfo(id PK, name, sex, age);
# 預設資料
1,Brand,0,22
2,Helenlyn,1,19
3,Sol,0,21
先初始化一個預設的表,裡面模擬幾條資料。此時沒有任何的事務未提交操作,所以回滾段是空的,如上圖。
start transaction;
delete from t_userinfo where id = 1;
update t_userinfo set name = 'Helenlyn...' where id = 2;
insert into t_userinfo(name, sex, age) valus ('Lili', 1, 18);
還未執行commit 或者 rollback,所以事務處於未提交的狀態
綜上,我們可以看出Commit之前我們進行如下操作:
我們上面說了,不是所有的操作最終都會commit,如果失敗,事務rollback,就可以通過回滾儲存區中的undo紀錄檔對操作進行回滾。
如果成功commit,則整體提交成功了
可以看到:
如果失敗並執行rollback,則全部回滾