MySQL底層原理綜合描述

1、概念


1.1 數據庫事務:簡單的說事務就是一組原子性的SQL語句。可以將這組語句理解成一個工作單元,要麼全部執行要麼都不執行。默認MySQL中自動提交時開啓的(start transaction)事務的ACID特性如下:

原子性:事務中的所有操作要麼全部提交成功,要麼全部失敗回滾。場景:UPDATE cs_user SET age = 18 , gender = '女' WHERE id = 4。要麼全部更新要麼更新失敗,不會出現age更新成功,gender更新失敗。

一致性:據庫總是從給一個一致性的狀態轉換到另一個一致性的狀態。場景:比如規定某個表的字段age大於等於12小於18時,字段type爲青少年,而數據庫中存在age=16的時候,type='兒童'。

隔離性:一個事務所做的修改在提交之前對其它事務是不可見的。兩個以上的事務不會出現交錯執行的狀態.因爲這樣可能會導致數據不一致。

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

事務的併發問題

  1、髒讀:事務A讀取了事務B更新的數據,然後B回滾操作,那麼A讀取到的數據是髒數據

  2、不可重複讀:事務 A 多次讀取同一數據,事務 B 在事務A多次讀取的過程中,對數據作了更新並提交,導致事務A多次讀取同一數據時,結果 不一致。

   3、幻讀:系統管理員A將數據庫中所有學生的成績從具體分數改爲ABCDE等級,但是系統管理員B就在這個時候插入了一條具體分數的記錄,當系統管理員A改結束後發現還有一條記錄沒有改過來,就好像發生了幻覺一樣,這就叫幻讀。

  小結:不可重複讀的和幻讀很容易混淆,不可重複讀側重於修改,幻讀側重於新增或刪除。解決不可重複讀的問題只需鎖住滿足條件的行,解決幻讀需要鎖表

事務的隔離級別如下:

READ UNCOMMITTED(讀未提交):事務中的修改即使未提交也是對其它事務可見

READ COMMITTED(讀提交):事務提交後所做的修改纔會被另一個事務看見,可能產生一個事務中兩次查詢的結果不同。

REPEATABLE READ(可重讀):只有當前事務提交才能看見另一個事務的修改結果。解決一個事務中兩次查詢的結果不同的題。

SERIALIZABLE(串行化):只有一個事務提交之後纔會執行另一個事務。

mysql默認的事務隔離級別爲repeatable-read

事務隔離級別 髒讀 不可重複讀 幻讀
讀未提交(read-uncommitted)
不可重複讀(read-committed)
可重複讀(repeatable-read)
串行化(serializable)


1.2 數據庫引擎



       數據庫的索引有InnoDB引擎、MyISAM引擎、Archive引擎、CSV引擎、Memory引擎、Federated引擎、Mrg_MyISAM引擎和NDB集羣引擎。

InnoDB引擎:

1.將數據存儲在表空間中,表空間由一系列的數據文件組成,由InnoDB管理;2.支持每個表的數據和索引存放在單獨文件中(innodb_file_per_table);3.支持事務,採用MVCC來控制併發,並實現標準的4個事務隔離級別,支持外鍵;4.索引基於聚簇索引建立,對於主鍵查詢有較高性能;5.數據文件的平臺無關性,支持數據在不同的架構平臺移植;6.能夠通過一些工具支持真正的熱備。如XtraBackup等;7.內部進行自身優化如採取可預測性預讀,能夠自動在內存中創建hash索引等。

MyISAM引擎:

1.MySQL5.1中默認,不支持事務和行級鎖;2.提供大量特性如全文索引、空間函數、壓縮、延遲更新等;3.數據庫故障後,安全恢復性差;4.對於只讀數據可以忍受故障恢復,MyISAM依然非常適用;5.日誌服務器的場景也比較適用,只需插入和數據讀取操作;6.不支持單表一個文件,會將所有的數據和索引內容分別存在兩個文件中;7.MyISAM對整張表加鎖而不是對行,所以不適用寫操作比較多的場景;8.支持索引緩存不支持數據緩存。

Archive引擎:

1.只支持insert和select操作;2.緩存所有的寫數據並進行壓縮存儲,支持行級鎖但不支持事務;3.適合高速插入和數據壓縮,減少IO操作,適用於日誌記錄和歸檔服務器。

Blackhole引擎:沒有實現任何存儲機制,會將插入的數據進行丟棄,但會存儲二進制日誌。會在一些特殊需要的複製架構的環境中使用。

CSV引擎:可以打開CSV文件存儲的數據,可以將存儲的數據導出,並利用excel打開。可以作爲一種數據交換的機制使用。

Memory引擎:將數據在內存中緩存,不消耗IO。存儲數據速度較快但不會被保留,一般作爲臨時表的存儲被使用。

Federated引擎:能夠訪問遠程服務器上的數據的存儲引擎。能夠建立一個連接連到遠程服務器。

Mrg_MyISAM引擎:將多個MYISAM表合併爲一個。本身並不存儲數據,數據存在MyISAM表中間。

NDB集羣引擎:MySQL Cluster專用。


2、引擎原理

索引本質:MySQL官方對索引的定義爲:索引(Index)是幫助MySQL高效獲取數據的數據結構。

2.1 MyISAM索引實現

MyISAM引擎使用B+Tree作爲索引結構,葉節點的data域存放的是數據記錄的地址。下圖是MyISAM索引的原理圖:

這裏設表一共有三列,假設我們以Col1爲主鍵,則圖8是一個MyISAM表的主索引(Primary key)示意。可以看出MyISAM的索引文件僅僅保存數據記錄的地址。在MyISAM中,主索引和輔助索引(Secondary key)在結構上沒有任何區別,只是主索引要求key是唯一的,而輔助索引的key可以重複。如果我們在Col2上建立一個輔助索引,則此索引的結構如下圖所示:

 

同樣也是一顆B+Tree,data域保存數據記錄的地址。因此,MyISAM中索引檢索的算法爲首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,則取出其data域的值,然後以data域的值爲地址,讀取相應數據記錄。

MyISAM的索引方式也叫做“非聚集”的,之所以這麼稱呼是爲了與InnoDB的聚集索引區分。

2.2 InnoDB索引實現

雖然InnoDB也使用B+Tree作爲索引結構,但具體實現方式卻與MyISAM截然不同。

第一個重大區別是InnoDB的數據文件本身就是索引文件。從上文知道,MyISAM索引文件和數據文件是分離的,索引文件僅保存數據記錄的地址。而在InnoDB中,表數據文件本身就是按B+Tree組織的一個索引結構,這棵樹的葉節點data域保存了完整的數據記錄。這個索引的key是數據表的主鍵,因此InnoDB表數據文件本身就是主索引。

是InnoDB主索引(同時也是數據文件)的示意圖,可以看到葉節點包含了完整的數據記錄。這種索引叫做聚集索引。因爲InnoDB的數據文件本身要按主鍵聚集,所以InnoDB要求表必須有主鍵(MyISAM可以沒有),如果沒有顯式指定,則MySQL系統會自動選擇一個可以唯一標識數據記錄的列作爲主鍵,如果不存在這種列,則MySQL自動爲InnoDB表生成一個隱含字段作爲主鍵,這個字段長度爲6個字節,類型爲長整形。

第二個與MyISAM索引的不同是InnoDB的輔助索引data域存儲相應記錄主鍵的值而不是地址。換句話說,InnoDB的所有輔助索引都引用主鍵作爲data域。例如,圖11爲定義在Col3上的一個輔助索引:

是InnoDB主索引(同時也是數據文件)的示意圖,可以看到葉節點包含了完整的數據記錄。這種索引叫做聚集索引。因爲InnoDB的數據文件本身要按主鍵聚集,所以InnoDB要求表必須有主鍵(MyISAM可以沒有),如果沒有顯式指定,則MySQL系統會自動選擇一個可以唯一標識數據記錄的列作爲主鍵,如果不存在這種列,則MySQL自動爲InnoDB表生成一個隱含字段作爲主鍵,這個字段長度爲6個字節,類型爲長整形。

第二個與MyISAM索引的不同是InnoDB的輔助索引data域存儲相應記錄主鍵的值而不是地址。換句話說,InnoDB的所有輔助索引都引用主鍵作爲data域。例如,圖11爲定義在Col3上的一個輔助索引。

1.聚集索引
聚集索引是按每張表的主鍵構造的一顆B+樹,並且葉節點中存放着整張表的行記錄數據,因此也讓聚集索引的節點成爲數據頁,這個特性決定了索引組織表中數據也是索引的一部分。由於實際的數據頁只能按照一顆B+樹進行排序,所以每張表只能擁有一個聚集索引。查詢優化器非常傾向於採用聚集索引,因爲其直接存儲行數據,所以主鍵的排序查詢和範圍查找速度非常快。
不是物理上的連續,而是邏輯上的,不過在剛開始時數據是順序插入的所以是物理上的連續,隨着數據增刪,物理上不再連續。
2.輔助索引
輔助索引頁級別不包含行的全部數據。葉節點除了包含鍵值以外,每個葉級別中的索引行中還包含了一個書籤,該書籤用來告訴InnoDB哪裏可以找到與索引相對應的行數據。其中存的就是聚集索引的鍵。
輔助索引的存在並不影響數據在聚集索引的結構組織。InnoDB會遍歷輔助索引並通過葉級別的指針獲得指向主鍵索引的主鍵,然後通過主鍵索引找到一個完整的行記錄。當然如果只是需要輔助索引的值和主鍵索引的值,那麼只需要查找輔助索引就可以查詢出索要的數據,就不用再去查主鍵索引了。

索引使用策略及優化

MySQL的優化主要分爲結構優化(Scheme optimization)和查詢優化(Query optimization)。

最左前綴原理與相關優化

MySQL中的索引可以以一定順序引用多個列,這種索引叫做聯合索引,一般的,一個聯合索引是一個有序元組<a1, a2, …, an>,其中各個元素均爲數據表的一列。單列索引可以看成聯合索引元素數爲1的特例。

條件按照 a1,a2...an 的順序索引纔會生效。例如索引3列(a1,a2,a3)

  (1)....where   a1=1 and a2=1 and a3=1    三個列的索引都生效。

  (2)....where   a1=1     a1索引都生效。

  (3)....where   a1=1 and a3=1   a1索引都生效,a3無法生效

(4) 填坑---讓a3生效:

    SELECT * FROM employees WHERE a1=1  AND title IN (SELECT DISTINCT(a2) FROM employees)  AND a3=1;

(5)  ....where   a3=1   索引無法生效

(6)....where   a1=1 and a2 like ’po%‘    索引生效 

(7)範圍列可以用到索引(必須是最左前綴),但是範圍列後面的列無法用到索引。同時,索引最多用於一個範圍列,因此如果查詢條件中有兩個範圍列則無法全用到索引。

....where   a1<10 and a2 like ’po%‘   a2索引無效 

(8)同時,用了“between”並不意味着就是範圍查詢。

....where   a1 BETWEEN 1AND  12  AND a2=1 AND a3 BETWEEN 4 AND 8;

看起來是用了兩個範圍查詢,但作用於a1 上的“BETWEEN”實際上相當於“IN”,也就是說a1實際是多值精確匹配。可以看到這個查詢用到了索引全部三個列。因此在MySQL中要謹慎地區分多值匹配和範圍匹配,否則會對MySQL的行爲產生困惑。


3、事務的隔離級別實驗:

1、查看數據庫事務

mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set, 1 warning (0.00 sec)

2、準備數據

mysql> use test;
Database changed
mysql> select * from users;
+----+------+------+
| id | name | age  |
+----+------+------+
|  1 | asd  |   12 |
|  2 | asd1 |   12 |
|  3 | q111 |   11 |
+----+------+------+
3 rows in set (0.01 sec)

3、讀未提交

(1)打開一個客戶端A,並設置當前事務模式爲read uncommitted(未提交讀)查詢表age的初始值:

mysql> set session transaction isolation level read uncommitted;
Query OK, 0 rows affected (0.00 sec)

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from users;
+----+------+------+
| id | name | age  |
+----+------+------+
|  1 | asd  |   12 |
|  2 | asd1 |   12 |
|  3 | q111 |   11 |
+----+------+------+
3 rows in set (0.01 sec)

(2)在客戶端A的事務提交之前,打開另一個客戶端B,更新表age,但是沒有提交。

mysql> set session transaction isolation level read uncommitted;
Query OK, 0 rows affected (0.00 sec)

mysql>  start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> use test
Database changed
mysql> update users set age=age+10 where id=1;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from users;
+----+------+------+
| id | name | age  |
+----+------+------+
|  1 | asd  |   22 |
|  2 | asd1 |   12 |
|  3 | q111 |   11 |
+----+------+------+
3 rows in set (0.00 sec)

(3)這時,雖然客戶端B的事務還沒提交,但是客戶端A就可以查詢到B已經更新的數據:

這是A客戶端查的結果

mysql>  select * from users;
+----+------+------+
| id | name | age  |
+----+------+------+
|  1 | asd  |   22 |
|  2 | asd1 |   12 |
|  3 | q111 |   11 |
+----+------+------+
3 rows in set (0.01 sec)

(4)一旦客戶端B的事務因爲某種原因回滾,所有的操作都將會被撤銷,那客戶端A查詢到的數據其實就是髒數據:

mysql> rollback;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from users;
+----+------+------+
| id | name | age  |
+----+------+------+
|  1 | asd  |   12 |
|  2 | asd1 |   12 |
|  3 | q111 |   11 |
+----+------+------+
3 rows in set (0.00 sec)

(5)查看A客戶端

mysql>  select * from users;
+----+------+------+
| id | name | age  |
+----+------+------+
|  1 | asd  |   12 |
|  2 | asd1 |   12 |
|  3 | q111 |   11 |
+----+------+------+
3 rows in set (0.00 sec)

mysql>  select * from users;
+----+------+------+
| id | name | age  |
+----+------+------+
|  1 | asd  |   22 |
|  2 | asd1 |   12 |
|  3 | q111 |   11 |
+----+------+------+
3 rows in set (0.01 sec)

mysql>  select * from users;
+----+------+------+
| id | name | age  |
+----+------+------+
|  1 | asd  |   12 |
|  2 | asd1 |   12 |
|  3 | q111 |   11 |
+----+------+------+
3 rows in set (0.00 sec)

所以讀未提交的事務隔離級別具有髒讀,不可重複度,幻讀的特性。

4、讀已提交

(1)打開一個客戶端A,並設置當前事務模式爲read committed(讀已提交),查詢age

mysql> set session transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> use test;
Database changed
mysql> select * from users;
+----+------+------+
| id | name | age  |
+----+------+------+
|  1 | asd  |   12 |
|  2 | asd1 |   12 |
|  3 | q111 |   11 |
+----+------+------+
3 rows in set (0.01 sec)

(2)在客戶端A的事務提交之前,打開另一個客戶端B,更新age:

mysql>  set session transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)

mysql>  start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> use test
Database changed
mysql> update users set age=age+10 where id=1;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from users;
+----+------+------+
| id | name | age  |
+----+------+------+
|  1 | asd  |   22 |
|  2 | asd1 |   12 |
|  3 | q111 |   11 |
+----+------+------+
3 rows in set (0.00 sec)

(3)這時,客戶端B的事務還沒提交,客戶端A不能查詢到B已經更新的數據,解決了髒讀問題:

mysql> select * from users;
+----+------+------+
| id | name | age  |
+----+------+------+
|  1 | asd  |   12 |
|  2 | asd1 |   12 |
|  3 | q111 |   11 |
+----+------+------+
3 rows in set (0.01 sec)

mysql> select * from users;
+----+------+------+
| id | name | age  |
+----+------+------+
|  1 | asd  |   12 |
|  2 | asd1 |   12 |
|  3 | q111 |   11 |
+----+------+------+
3 rows in set (0.00 sec)

(4)客戶端B的事務提交

mysql> commit;
Query OK, 0 rows affected (0.01 sec)

(5)客戶端A執行與上一步相同的查詢,結果 與上一步不一致,即產生了不可重複讀的問題

mysql> select * from users;
+----+------+------+
| id | name | age  |
+----+------+------+
|  1 | asd  |   12 |
|  2 | asd1 |   12 |
|  3 | q111 |   11 |
+----+------+------+
3 rows in set (0.00 sec)

mysql> select * from users;
+----+------+------+
| id | name | age  |
+----+------+------+
|  1 | asd  |   22 |
|  2 | asd1 |   12 |
|  3 | q111 |   11 |
+----+------+------+
3 rows in set (0.00 sec)

3、可重複讀

     (1)打開一個客戶端A,並設置當前事務模式爲repeatable read,查詢表account的所有記錄

mysql> set session transaction isolation level repeatable read;
Query OK, 0 rows affected (0.00 sec)

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> use test
Database changed
mysql> select * from users;
+----+------+------+
| id | name | age  |
+----+------+------+
|  1 | asd  |   12 |
|  2 | asd1 |   12 |
|  3 | q111 |   11 |
+----+------+------+
3 rows in set (0.01 sec)

(2)在客戶端A的事務提交之前,打開另一個客戶端B,更新

mysql> set session transaction isolation level repeatable read;
Query OK, 0 rows affected (0.00 sec)

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> use test;
Database changed
mysql> update users set age=age+8 where id=1;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from users;
+----+------+------+
| id | name | age  |
+----+------+------+
|  1 | asd  |   20 |
|  2 | asd1 |   12 |
|  3 | q111 |   11 |
+----+------+------+
3 rows in set (0.00 sec)

(3)A查詢,發現沒有變化   解決髒讀

mysql> select * from users;
+----+------+------+
| id | name | age  |
+----+------+------+
|  1 | asd  |   12 |
|  2 | asd1 |   12 |
|  3 | q111 |   11 |
+----+------+------+
3 rows in set (0.00 sec)

(4)B提交,後查詢A,還是沒有變化,,,代表多次讀寫數據一致。沒有出現不可重複讀的問題

mysql> select * from users;
+----+------+------+
| id | name | age  |
+----+------+------+
|  1 | asd  |   12 |
|  2 | asd1 |   12 |
|  3 | q111 |   11 |
+----+------+------+
3 rows in set (0.00 sec)

(5)在客戶端A,接着執行update users  age= age - 2 where id = 1,age沒有變成12-2=10,而是20 -2 =18,數據的一致性倒是沒有被破壞。可重複讀的隔離級別下使用了MVCC機制,select操作不會更新版本號,是快照讀(歷史版本);insert、update和delete會更新版本號,是當前讀(當前版本)。

mysql> update users set age=age-2 where id=1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from users;
+----+------+------+
| id | name | age  |
+----+------+------+
|  1 | asd  |   18 |
|  2 | asd1 |   12 |
|  3 | q111 |   11 |
+----+------+------+
3 rows in set (0.00 sec)

 4.串行化

        (1)打開一個客戶端A,並設置當前事務模式爲serializable,查詢age的初始值

        (2)打開一個客戶端B,並設置當前事務模式爲serializable,插入一條記錄報錯,表被鎖了插入失敗,mysql中事務隔離級別爲serializable時會鎖表,因此不會出現幻讀的情況,這種隔離級別併發性極低,開發中很少會用到。

補充:

  1、事務隔離級別爲讀提交時,寫數據只會鎖住相應的行

  2、事務隔離級別爲可重複讀時,如果檢索條件有索引(包括主鍵索引)的時候,默認加鎖方式是next-key 鎖;如果檢索條件沒有索引,更新數據時會鎖住整張表。一個間隙被事務加了鎖,其他事務是不能在這個間隙插入記錄的,這樣可以防止幻讀。

  3、事務隔離級別爲串行化時,讀寫數據都會鎖住整張表

   4、隔離級別越高,越能保證數據的完整性和一致性,但是對併發性能的影響也越大。

 

READ UNCOMMITTED (未提交讀) :隔離級別:0.  哪個問題都不能解決

原理: 事務A和事務B,事務B可以讀取事務A未提交的記錄。會出現髒讀,因爲事務A可能會回滾操作,導致數據發生變化。

READ COMMITTED (提交讀) :隔離級別:1.   可以解決髒讀 。

  原理: 事務中只能看到已提交的修改,提交讀這種隔離級別保證了讀到的任何數據都是提交的數據,避免了髒讀,但是不保證事務重新讀的時候能讀到相同的數據,因爲在每次數據讀完之後其他事務可以修改剛纔讀到的數據。

REPEATABLE READ (可重複讀) :隔離級別:2. 可以解決髒讀和不可重複讀,實現不幻讀,需要加鎖

原理:在InnoDB中是這樣的:RR隔離級別保證對讀取到的記錄加鎖 (記錄鎖),同時保證對讀取的範圍加鎖,新的滿足查詢條件的記錄不能夠插入 (間隙鎖),因此不存在幻讀現象。但是標準的RR只能保證在同一事務中多次讀取同樣記錄的結果是一致的,而無法解決幻讀問題。InnoDB的幻讀解決是依靠MVCC的實現機制做到的。Mysql默認的隔離級別是RR。

InnoDB的幻讀解決是依靠MVCC的實現機制:   (增加系統版本號,每次事務操作,會比較系統版本號)                      
          InnoDB爲每行記錄添加了一個版本號(系統版本號),每當修改數據時,版本號加一。在讀取事務開始時,系統會給事務一個當前版本號,事務會讀取版本號<=當前版本號的數據,這時就算另一個事務插入一個數據,並立馬提交,新插入這條數據的版本號會比讀取事務的版本號高,因此讀取事務讀的數據還是不會變。例如:此時books表中有5條數據,版本號爲1  事務A,系統版本號2:select * from books;因爲1<=2所以此時會讀取5條數據。 事務B,系統版本號3:insert into books ...,插入一條數據,新插入的數據版本號爲3,而其他的數據的版本號仍然是2,插入完成之後commit,事務結束。  事務A,系統版本號2:再次select * from books;只能讀取<=2的數據,事務B新插入的那條數據版本號爲3,因此讀不出來,解決了幻讀的問題。

SERIALIZABLE (可串行化):隔離級別:3.

原理:該隔離級別會在讀取的每一行數據上都加上鎖,退化爲基於鎖的併發控制,即LBCC。可以解決髒讀不可重複讀和幻讀—相當於鎖表 

需要注意的是,MVCC只在RC和RR兩個隔離級別下工作,其他兩個隔離級別都和MVCC不兼容。


Mysql索引命中規則
           最左匹配原則 
                 1、先定位該sql的查詢條件,有哪些,那些是等值的,那些是範圍的條件。 
                  2、等值的條件去命中索引最左邊的一個字段,然後依次從左往右命中,範圍的放在最後。

           一條sql語句要執行完成需要經歷什麼樣的過程 
                  當一條sql語句提交給mysql數據庫進行查詢的時候需要經歷以下幾步 
                 1、先在where解析這一步把當前的查詢語句中的查詢條件分解成每一個獨立的條件單元 
                 2、mysql會自動將sql拆分重組 
                 3、然後where條件會在B-tree index這部分進行索引匹配,如果命中索引,就會定位到指定的table records位置。如果沒有命中,則只能採用全部掃描的方式 
                 4、根據當前查詢字段返回對應的數據值

 

Undo原理:(備份舊數據)

         在操作任何數據之前,首先將數據備份到一個地方(這個存儲數據備份的地方稱爲Undo Log)。然後進行數據的修改。如果出現了錯誤或者用戶執行了ROLLBACK語句,系統可以利用Undo Log中的備份將數據恢復到事務開始之前的狀態。

Redo原理:(保存最新數據)

         和Undo Log相反,Redo Log記錄的是新數據的備份。在事務提交前,只要將Redo Log持久化即可,不需要將數據持久化。當系統崩潰時,雖然數據沒有持久化,但是Redo Log已經持久化。系統可以根據Redo Log的內容,將所有數據恢復到最新的狀態。

MVCC的設計目的是什麼,怎麼使用版本號判斷數據的可見性
        MVCC是一種多版本併發控制機制。鎖機制可以控制併發操作,但是其系統開銷較大,而MVCC可以在大多數情況下代替行級鎖,使用MVCC,能降低其系統開銷。

       人們一般把基於鎖的併發控制機制稱成爲悲觀機制,而把MVCC機制稱爲樂觀機制。這是因爲鎖機制是一種預防性的,讀會阻塞寫,寫也會阻塞讀,當鎖定粒度較大,時間較長時併發性能就不會太好;而MVCC是一種後驗性的,讀不阻塞寫,寫也不阻塞讀,等到提交的時候才檢驗是否有衝突,由於沒有鎖,所以讀寫不會相互阻塞,從而大大提升了併發性能。

       MVCC的一種簡單實現是基於CAS(Compare-and-swap)思想的有條件更新(Conditional Update)。普通的update參數只包含了一個keyValueSet’,Conditional Update在此基礎上加上了一組更新條件conditionSet { … data[keyx]=valuex, … },即只有在D滿足更新條件的情況下才將數據更新爲keyValueSet’;否則,返回錯誤信息。

參考文獻:

[1] MySQL運行機制原理&架構

[2] MySQL的四種事務隔離級別

[3] MySQL索引背後的數據結構及算法原理

[4] 基於Mysql數據庫原理特性以及底層機制的深入研究理解

[5] 輕鬆理解MYSQL MVCC 實現機制

[6] innodb下的記錄鎖,間隙鎖,next-key鎖

參考文獻:

[1] MySQL運行機制原理&架構

[2] MySQL的四種事務隔離級別

[3] MySQL索引背後的數據結構及算法原理

[4] 基於Mysql數據庫原理特性以及底層機制的深入研究理解

[5] 輕鬆理解MYSQL MVCC 實現機制

[6] innodb下的記錄鎖,間隙鎖,next-key鎖

 

 

 

 

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