mysql InnoDB事務
參考書籍《mysql是怎樣運行的》
以及極客時間《mysql實戰45講》
本文總結事務相關的概念,事務相關的命令等,具體持久性,原子性,隔離性如何實現,會在後續的學習中進行補充
一丶事務
上一篇關於buffer pool的學習中,我們學習Buffer pool相關知識,innodb再對某個頁面進行讀寫訪問時,會將這個頁面讀到buffer pool 中,之後如果修改了某個頁面,也不會立即刷新到磁碟,而只是將緩衝頁面的控制塊添加到flush 鏈表中,之後某個時間點(後台定時任務執行緒每隔一定時間將flush 鏈表中的臟頁刷新到磁碟,或者新的頁面需要緩衝,將LRU鏈表中一些臟頁刷盤)。那麼如果mysql服務突然崩潰,或者伺服器突然斷電,豈不是已經提交的事務
將丟失?
事務是指是程式中一系列嚴密的邏輯操作,而且所有操作必須全部成功完成,否則在每個操作中所作的所有更改都會被撤消
這裡保證已經提交事務一定可以持久化到磁碟的就是redo log。類似如果事務執行到一半需要回滾如何實現昵,這就是undo log實現的版本控制鏈的作用。
二丶事務特性
1.原子性
要麼多個操作都執行,要麼多個操作都不執行,不可存在中間狀態。但是現實世界中一個業務存在多個步驟,這些步驟抽象為資料庫操作又存在多個,一個資料庫操作又可分為多步(比如先修改緩衝頁,再刷新磁碟)任何一個時間點都可能發生意想不到的錯誤,使操作無法執行下去,所以需要保證:如果再執行過程中發生了錯誤
,就把已經執行的操作恢復為執行前的樣子。
2.隔離性
對於現實世界中狀態轉換對應的某些資料庫操作來說,不僅僅需要保證原子性,還需要保證其他資料庫操作造成狀態轉換不會影響到本次狀態轉換。這便是隔離性
3.一致性
只有符合約束的數據才是有效(年齡再符合規定的範圍,房價不能為負數)如果數據中的數據全部符合現實世界的約束,我們就說這些數據具備一致性
。如何實現一致性
- 資料庫本身可以保證一定的一致性(主鍵,唯一索引保證不可重複,申明某些列not null拒絕null值的插入)甚至可以定義一些觸發器進行限定
- 更多一致性操作,需要crud程式設計師進行限制
如果資料庫操作不符合原子性(轉錢扣了轉賬者,但是收款的人錢數沒有增加)或者不符合隔離性(兩個操作並發,第二個操作讀到第一個操作沒有提交的數據,然後第二個操作後寫回,發生了臟寫)這也是不符合一致性要求——資料庫中原子性和隔離性都是保證一致性的一種手段
4.持久性
當現實世界中的一個狀態轉換完成後,這個轉換結果需要永久保留,這稱為持久性
,現實世界中狀態轉換映射到數據中時,持久性意味著轉換對應的數據需要持久化到磁碟中,無論發生什麼事故,本次轉換操作的影響都不應該丟失(損壞磁碟除外doge)
三丶事務的狀態
- 活動的:事務對應的資料庫操作正在執行過程中時
- 部分提交的:當事務中最後一個操作執行完成,但是由於操作都是在記憶體中執行,造成了影響沒用刷新到磁碟時
- 失敗的:事務處於活動狀態或者部分提交時,約到某些錯誤而無法繼續執行,或者任務終止事務的執行,事務就稱為失敗的
- 中止的:事務執行到一半,需要撤銷對資料庫造成的影響進行撤銷,
回滾
,當回滾操作執行完畢,稱為終止的 - 提交的:處於
部分狀態的事務
對應操作刷新到磁碟,稱為提交的
四丶mysql中的事務語法
1.開啟事務
-
Begin
-
Start Transaction
該命令可以跟隨如下修飾符,多個修飾符使用逗號分隔,如
Start Transaction read only,with consistent snapshot
-
read only
標識當前事務是一個只讀事務,屬於該事務的資料庫操作只能進行讀操作(但是可以改當前會話中的臨時表)(為什麼只讀還需要事務,因為需要獲得一致性視圖,不同的隔離級別會讀到不同的數據,比如你想統計流水表中本月每一個顧客的消費資訊,先統計了總流水Sum,然後依次統計每一個用戶的流水,如果沒用事務,第後續的對每一個顧客的統計之和可能讀到最新的數據(用戶新增了消費),而導致總流水和每一個用戶流水之和不等的情況)
-
read write
標記當前事務是讀寫事務
-
with consistent snapshot
啟動一致性讀
-
begin/start transaction 命令並不是一個事務的起點,在執行到它們之後的第一個操作
InnoDB 表的語句,事務才真正啟動。(一致性視圖是在第執行第一個快照讀語句時創建的)
如果你想要馬上啟動一個事務,可以使用 start transaction with consistent snapshot 這個命令。(一致性視圖是在執行 start transaction with consistent snapshot 時創建的)
2.提交事務
-
commit
-
commit work and chain
提交當前事務並開啟下一個事務,如果執行 commit work and chain,則是提交事務並自動啟動下一個事務,這樣省去了再次執行 begin 語句的開銷
3.手動中止事務
roll back
,程式設計師可以手段roll back進行回滾事務,如果事務在執行的過程中遇到一些錯誤,比如發生了死鎖,會回滾整個事務
4.自動提交
mysql 有一個系統變數autocommit
來控制是否自動提交事務,如果不顯示的使用開啟事務的命令,那麼每一條語句就視為一個獨立的事務。關閉自動提交的方式有:手動開啟事務,設置自動提交為OFF,這時候需要手動提交或者進行回滾。
6.隱式提交
mysql中如果輸入了一些特定的語句,即便不是commit 命令也會提交事務。如
-
執行ddl,定義資料庫對象的命令,比如建立表,修改表,以及視圖,存儲過程等
-
隱式的使用或者修改mysql資料庫中的表
使用
alter user
,create user
,drop user
等語句的時候會提交前面語句屬於的事務 -
事務控制or關於鎖定的語句
如果一個事務還沒有提交,或者回滾的時候,又開啟一個新事務,或者修改
autocommit
的值從OFF 到ON的時候也會提交事務。使用lock tables,unlock tables等關於鎖定的語句也會提交事務 -
載入數據的語句
比如使用load data等語句也會提交事務
-
關於mysql複製的語句
比如
start slave
,stop slave
也會提交事務 -
其他語句
比如
optimize table
等
7.保存點
savepoint 保存點名稱
,可以開啟一個保存點,使用rollback to 保存點名稱
可以回滾到指定保存點,使用release savepoint 保存點
可以釋放保存點,保存點如同遊戲的存檔,避免我們從頭開始,心態炸裂
五丶小心長事務
長事務意味著系統裡面會存在很老的事務視圖。由於這些事務隨時可能訪問資料庫裡面的任何數據,所以這個事務提交之前,資料庫裡面它可能用到的回滾記錄都必須保留,這就會導致大量佔用存儲空間(記錄回滾資訊的undo log,需要一致存儲,佔用空間)可以在information_schema
庫的innodb_trx
這個表中查詢長事務的資訊