AUTOCOMMIT
Mysql預設自動認可,可以通過如下命令查看和修改:
mysql> SHOW VARIABLES LIKE 'AUTOCOMMIT';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | ON |
+---------------+-------+
1 row in set (0.00 sec)
mysql> SET AUTOCOMMIT = 1;
隱式鎖顯式鎖
InnoDB在開啟事務時,擷取隱式鎖,在事務提交或者復原時釋放鎖,InnoDB根據隔離等級自動處理鎖。
但InnoDB也支援顯式鎖:
SELECT ... FOR UPDATE
SELECT ... LOCK IN SHARE MODE
多版本並發控制(Multiversion Concurrency Controll MVCC)
第一點:
MVCC並不是MySql專屬的,Oracle,PostgreSQL等都在使用。
MVCC並沒有簡單地使用行鎖,而是使用“行層級鎖”(row-level locking)。MVCC的基本原理是:
在事務中儲存資料的快照,這意味著在一個事物裡能夠看到資料一致的視圖,而不用擔心這個事務運行多長時間,同時也意味著在同一個時刻不同事務看到的相同表裡的資料可能是不同的。
MVCC的基本特徵:
- 每行資料都存在一個版本,每次資料更新時都更新該版本
- 修改時Copy出目前的版本隨意修改,個事務之間無幹擾
- 儲存時比較版本號碼,如果成功(commit),則覆蓋原記錄;失敗則放棄copy(rollback)
InnoDB儲存引擎MVCC的實現策略:
在每一行資料中額外儲存兩個隱藏欄位:當前行建立時的版本號碼和刪除時的版本號碼(可能為空白)。每個事務又有自己的版本號碼,這樣事務內執行CRUD操作時,就通過版本號碼的比較來達到資料版本控制的目的。具體做法見下面的。
但是在網上又看到另外一種說法:
Innodb的實現方式是:
- 事務以獨佔鎖定的形式修改未經處理資料
- 把修改前的資料存放於undo log,通過復原指標與主要資料關聯
- 修改成功(commit)啥都不做,失敗則恢複undo log中的資料(rollback)
二者最本質的區別是,當修改資料時是否要獨佔鎖定定,如果鎖定了還算不算是MVCC? Innodb的實現真算不上MVCC,因為並沒有實現核心的多版本共存,undo log中的內容只是序列化的結果,記錄了多個事務的過程,不屬於多版本共存。但理想的MVCC是難以實現的,當事務僅修改一行記錄使用理想的MVCC模式是沒有問題的,可以通過比較版本號碼進行復原;但當事務影響到多行資料時,理想的MVCC據無能為力了。 比如,如果Transaciton1執行理想的MVCC,修改Row1成功,而修改Row2失敗,此時需要復原Row1,但因為Row1沒有被鎖定,其資料可能又被Transaction2所修改,如果此時復原Row1的內容,則會破壞Transaction2的修改結果,導致Transaction2違反ACID。 理想MVCC難以實現的根本原因在於企圖通過樂觀鎖代替二段提交。修改兩行資料,但為了保證其一致性,與修改兩個分布式系統中的資料並無區別,而二提交是目前這種情境保證一致性的唯一手段。二段提交的本質是鎖定,樂觀鎖的本質是消除鎖定,二者矛盾,故理想的MVCC難以真正在實際中被應用,Innodb只是借了MVCC這個名字,提供了讀的非阻塞而已。