《MySQL技術內幕-InnoDB存儲引擎》學習筆記五-數據庫事務
2019-07-18 ヾ(◍°∇°◍)ノ゙ 不要攔着我 我還能學一會兒
第7章 事務的東東
簡單的說說:就是數據庫區別於文件系統的重要特徵之一了。就是事務是訪問更新數據庫數據的一個單元,在這個事務單元中所有的修改,要麼都成功,要麼都失敗。好像就醬紫。
概述與分類
常說的數據庫特性
- **原子性(atomicity):**就是事務操作爲最小單位,要麼都成功,要麼都失敗。
- **一致性(consistency):**不知道是啥 (ノ`Д)ノ
- **隔離性(isolation):**不同事務之間的數據不會相互影響。
- **持久性(durability):**事務完成後,數據就爲永久性的了(數據不可逆並持久化存儲於存儲系統當中)
就是常說的啥ACID特性。具體幹啥用的,不知道。但並不是所有數據庫都完全滿足這4個特性的。【比如:oracle 數據庫,默認事務級別爲READ COMMITTED,就不滿足隔離性的了。】
事務的分類
- 扁平事務 :就是簡單的單個 begin 、commit、rollback這樣子。
- 帶有保存點的扁平事務:在一個事務中有好幾個保存點用於部分回滾的東東。
- 鏈事務:一個事務結束之後調用另一個事務。(之間有數據結果傳遞)
- 嵌套事務:一個事務中 調用另外的子事務。(常見存儲過程之間調用,好像相互調用會死鎖或死循環的樣子)
- 分佈式事務: 是多個節點間的扁平事務集合。(栗子:招行轉賬到工行,這個操作了兩個節點的數據。需要分佈式事務,要麼都成功,要麼都失敗。雖然這個事務常見處理時在業務層面完成的。)
注意:InnoDB是不支持嵌套事務的,ε=(´ο`*)))唉 。。。。。
事務特性的實現
數據庫的事務是要滿足ACID特性的:
- 隔離性:由 鎖 來實現
- 原子性、一致性、持久性:由數據庫的redo log 和 undo log 來實現;
redo log爲重做日誌,用來保證事務的原子性和持久性。(物理頁日誌)
undo log爲回滾日誌,用來保證事務的一致性。(邏輯行日誌)
關於各種日誌
redo 重做日誌
是InnoDB開啓事務的時候,就一直在記錄重做日誌,在commit的時候,會把所有日誌寫到重做日誌文件進行持久化保存。【這個動作爲同步fsync操作】
默認配置操作爲commit的時候同步,但是也可以配置 略
重做日誌,分爲兩個部分:內存中的重做日誌緩衝,和 重做日誌文件。
然後這裏面還有啥log block (重做日誌塊)、log group(重做日誌組)、LSN(日誌序列號)等等的東西,都不用管啦,引擎自行處理就好了。
查看重做日誌情況:
SHOW ENGINE INNODB STATUS;中的Log sequence ...Log flushed up to ...Last checkpoint at .......
看看就好了。
undo 回滾日誌
是一種邏輯日誌,用於將數據庫邏輯地恢復到原來的樣子。
show VARIABLES LIKE 'innodb_undo%'
可以用這個語句來查詢一點簡單的信息。
而關於這個回滾日誌的其他的東東,我也看不懂了(ノ`Д)ノ 反正都是InnoDB自己處理的。
其他操作
purge 清空操作
delete 和update 操作,並不會真正的刪除原有的記錄,只是標記頁記錄中的標誌位。真正的刪除是有purge這裏來操作完成的。
是按照一個history list 進行undo log 的查找,並處理清除數據的。對已其他的配置,正常人就不用去調整了。。。
group commit
就是一次同步刷新多個事務日誌到文件。略
以上這些亂七八糟的操作,反正都是建議按InnoDB原本的配置就可以了。(:з」∠)
事務控制
默認情況下,MySQL是自動提交的。就是在執行完一個sql之後,自動就會commit。
常用的語句命令
- start transaction | begin :顯示開啓事務
- commit: 顯示事務提交
- rollback:回滾操作,回滾會結束用戶事務,並撤銷爲提交的修改。
- savepoint identifier : 允許始終中添加多個保存點
- release savepoint identifier : 刪除事務保存點,如果沒有保存點會拋出異常
- rollback to [savepoint] identifier:回滾事務到保存點,但是並沒有結束事務
- set transaction:設置事務隔離級別。在前一篇鎖的筆記裏面有
這些的事務控制的命令,在做存儲過程的時候是會用上了,普通代碼的CURD是不會用到的
分佈式事務
InnoDB存儲引擎是支持XA事務的,也就是分佈式事務。(XA使用的是兩次提交的事務解決方案)
通常來說,分佈式事務是使用編程語言來完成操作的。比如:**Java的JTA(Java Transaction API)**可以很好的支持Mysql的分佈式事務,具體怎麼用。。。。。鬼知道啊。。。(ノ`Д)ノ 用到的時候再說吧,現在接手的業務還沒到這個級別。
事務的問題
循環提交
正常在存儲過程中循環更新數據的時候,雖然沒有顯示的提交【commit】,但是數據庫默認會自動提交的。也就是說,每一次的更新都會進行一次的日誌同步,這個是很會花時間的。【即使是用了BEGIN,並且在循環中沒有顯示commit】
所以,正確的加快速度的做法是,顯示的
START TRANSACION
開始事務,在完成後COMMIT
。這樣只會進行一次的重做日誌同步。
自動提交
這個就是前邊說的情況,默認情況下Mysql是自動提交的,在大數據更新的時候可能會影響速度。
自動回滾
說的是代碼(存儲過程)中使用異常捕獲,然後自動回滾:像這樣
CREATE PROCEDURE XXXXXXX() BEGIN DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK ; -- DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN ...插入異常日誌... END ; ......... END;
我覺的挺好啊,不過就是會丟失了,數據庫異常返回的信息而已 ╮(╯_╰)╭;
覺得這個異常捕獲可以做一些日誌的插入,還是很好的;
長事務
就是執行時間幾個小時的事務,需要進行分解爲小的事務來處理。(比如處理n億級別的數據)
雖然,這個級別的數據量我是遇不到的╮(╯_╰)╭
小結一下
這裏由於事務的情況,會建議使用row格式的二進制日誌。
然後主要就是最後一些事務上的問題需要開發的時候注意一下,以及事務開啓的命令要會用【在存儲過程中】。就醬紫即可
2019-07-26 小杭
最近一週一篇的學習進度,好累。。"( ̄(エ) ̄)ゞ