1、前述
相信我們開發中會遇到各種各樣的異常,或者請求外部接口的異常,當用戶端向我們的服務端發起一次請求的時候,通常在業務裡會做一些資料庫增删改查的操作,然後做一些業務邏輯處理來傳回響應給用戶端,但是代碼裡出現異常是不可避免的,這個時候就需要我們來做一些資料庫復原的操作,也就是事務復原,否則就會出現很多的髒資料,影響系統後續的業務處理,本文是自己的一篇記錄和了解
2、資料庫事務復原
說到資料庫事務復原,這裡想提一點,Redis 是不支援事務復原的,redis 是先對記憶體中的資料進行操作,再寫入日志,這樣可以防止 aof 檔案寫入許多錯誤的指令,而 Mysql 例如 innodb 是支援事務的,先寫 redlog ,再對資料進行操作,
3、資料庫事務特性 ACID
A:Atomicity,原子性說到底就是,一條繩子上的螞蚱,誰都不能出事,一起成功一起失敗
C:consistency,一緻性也可以叫做資料完整性,事務在送出執行以後,必須有狀态的改變
I:isolation,隔離性,并發的多個事務之間不能資料幹擾,互相獨立隔離
D:durability,持久性,當事務送出以後,對資料庫進行的資料狀态操作應該被記錄下來,持久化儲存
4、資料庫隔離級别
4.1 隔離概念:
隔離級别是在多個事務同時進行更改和執行查詢時,對性能和結果的可靠性、一緻性和重制性之間的平衡進行微調的設定。
4.1 隔離級别:
InnoDB提供了SQL:1992标準描述的所有四個事務隔離級别:
READ UNCOMMITTED 讀取未送出
READ COMMITTED 讀取已送出
REPEATABLE READ 可重複讀
SERIALIZABLE 串行化
InnoDB 的預設隔離級别是
REPEATABLE READ
4.1.1 READ UNCOMMITTED
如圖,為一次示例讀取未送出,
t1 開啟事務 A
t2 開啟事務 B
t3 事務 A 查詢 username = ‘tanxi’
t4 事務 B 修改值 username = 'tanxi02'
t5 事務 A 查詢 username = 'tanxi02'
很明顯可以看出,事務 A 讀取到了 事務 B 的未送出的資料,造成了髒讀,這是最不安全的隔離級别,這種隔離級别解決不了任何問題
4.1.2 READ COMMITTED
如圖,為一次示例讀取已送出
t1 開啟事務 A
t2 開啟事務 B
t3 事務 A 查詢 username = ‘tanxi’
t4 事務 B 修改值 username = 'tanxi02'
t5 事務 A 查詢 username = 'tanxi'
t6 事務 B 送出事務
t7 事務 A 查詢 username = 'tanxi02'
該隔離級别解決了 4.1.1 的髒讀,但是不能解決不可重複讀,這是不被允許的資料讀取方式
4.1.3 REPEATABLE READ
如圖,為一次示例可重複讀
t1 開啟事務 A
t2 開啟事務 B
t3 事務 A 查詢 username = ‘tanxi’
t4 事務 B 修改值 username = 'tanxi02'
t5 事務 A 查詢 username = 'tanxi'
t6 事務 B 送出事務
t7 事務 A 查詢 username = 'tanxi'
該隔離級别解決了不可重複讀的問題,事務 B 的事務送出沒有影響到事務 A 的查詢結果
4.1.4 SERIALIZABLE
如圖,為一次示例串行化
t1 開啟事務 A
t2 開啟事務 B
t3 事務 A 查詢 username = ‘tanxi’
t4 事務 B 修改值 username = 'tanxi02'
t5 事務 A 查詢 ,阻塞等待
t6 事務 B 送出事務
t7 事務 A 查詢 username = 'tanxi'
該隔離級别可以避免髒讀以及不可重複讀,但是會阻塞 sql,也就是寫讀不能并發。性能很差
5、總結說明
在 mysql 的 innodb 引擎中,InnoDB 引擎預設的行鎖算法.,Next-Key locks 可以避免幻讀,有興趣的同學可以去官網了解。https://dev.mysql.com/doc/refman/5.7/en/