mysql InnoDB事務

2022-11-01 06:00:20
參考書籍《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)

三丶事務的狀態

  1. 活動的:事務對應的資料庫操作正在執行過程中時
  2. 部分提交的:當事務中最後一個操作執行完成,但是由於操作都是在記憶體中執行,造成了影響沒用重新整理到磁碟時
  3. 失敗的:事務處於活動狀態或者部分提交時,約到某些錯誤而無法繼續執行,或者任務終止事務的執行,事務就稱為失敗的
  4. 中止的:事務執行到一半,需要復原對資料庫造成的影響進行復原,回滾,當回滾操作執行完畢,稱為終止的
  5. 提交的:處於部分狀態的事務對應操作重新整理到磁碟,稱為提交的

四丶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這個表中查詢長事務的資訊