首頁 > 軟體

MySQL的事務特性概念梳理總結

2022-07-11 10:00:05

重溫事務的概念

為什麼用事務、事務是什麼

我們規定了,做一件事情,只有成功和失敗!
用個很經典的例子舉例:
銀行轉賬,A向B轉賬十萬,能不能發生一遍付錢一邊沒收錢的情況?
現實中一定是A和B同時成功或者失敗,不能出現一邊成功另一邊失敗的情景,這就是事務的簡單例子。

那麼由這個例子我們想想事務其實是為了保證什麼?

假如:

  • 張三問羅老師借錢,借了錢沒寫借據
  • 這是做了事情,但是沒有依據,就算做成功了,也沒辦法證明。突出借據的重要性(永續性) redolog
  • 張三問羅老師借錢,羅老師同意了,可是張三不想借了

這是事情做成功了,關鍵點在於,我可不可以反悔。(張三去決定)突出回滾的重要性(原子性)undo log

所以**事務其實就是想要做的事情是一個整體!**事務的存在目的就是為了事情能夠正確成功的執行。

如果以資料庫的角度去看:

在關係型資料庫中,事務其實就是【一組原子性的SQL】或者說一個獨立不可分割的工作單元,如果資料庫引擎能成功的對資料庫參照該組查詢的全部語句,那麼就執行該組查詢,如果其中有任何一條語句因為崩潰或者其他原因無法執行,那麼所有的語句都不會執行,也就是說,事務內的語句,要麼全部執行成功,要麼全部執行失敗

那麼剛才那個轉賬的例子,讓我們去寫一個事務,應該怎麼寫?

查詢A賬戶的餘額是否大於10W塊錢從A賬戶餘額中減去10W塊錢在B賬戶餘額中增加10W塊錢

怎麼用事務

還記得怎麼寫事務的sql語句嗎?

--開啟一個事務
BEGIN;--等價於 START TRANSACTION;
--執行我們需要的SQL
--提交事務
COMMIT;
--回滾事務
ROLLBACK;

我們來模擬一下A的兩個賬戶(CMBC銀行、ICBC銀行)之間轉賬的事務

# 開啟轉賬事務
BEGIN;
SELECT BALANCE FROM BANK_CMBC WHERE USER_NAME = 'A的CMBC銀行賬戶';
# 這裡需要判斷餘額 是否大於等於 10W
UPDATE BANK_CMBC SET BALANCE = BALANCE - 100000 WHERE USER'A的CMBC銀行賬戶';
UPDATE BANK_ICBC SET BALANCE = BALANCE + 100000 WHERE USER'A的ICBC銀行賬戶';
# 這裡當然還需要記錄 記錄表 紀錄檔表 轉賬記錄表 等
SELECT * FROM BANK_CMBC;
SELECT * FROM BANK_ICBC;
--提交
COMMIT;
--或者回滾
ROLLBACK;
# BANK_CMBC 裡的餘額會減去10W 然後 BANK_ICBC賬戶增加10W,
# 這個就是我們事務的具體使用場景了,要麼全部成功要麼全部失敗!

我能不能只提交一部分事務,一部分事務不提交呢?
也可以,使用SAVEPOINT,但是呢,要記得提交

BEGIN;
SELECT BALANCE FROM BANK_CMBC WHERE USER_NAME = 'A的CMBC銀行賬戶';
# 這裡需要判斷餘額 是否大於等於 10W
UPDATE BANK_CMBC SET BALANCE = BALANCE - 100000 WHERE USER_NAME ='A的CMBC銀行賬戶';
SAVEPOINT A;--設定回滾點
UPDATE BANK_ICBC SET BALANCE = BALANCE + 100000 WHERE USER_NAME ='A的ICBC銀行賬戶';
# 這裡當然還需要記錄 記錄表 紀錄檔表 轉賬記錄表 等
# 回滾到儲存點
ROLLBACK TO A;
SELECT * FROM BANK_CMBC;
SELECT * FROM BANK_ICBC;
COMMIT;
# 這個時候我們的記錄是多少?
# 我們看一下 在SAVEPOINT 之前的語句都能正確提交,SAVEPOINT之後的語句因為我們手動回滾了他們是沒有被更改成的,這
# 就是SAVEPOINT的作用,他能夠在一個事務裡開啟一個巢狀事務。主事務和巢狀事務屬於同一個事務,巢狀事務出錯回滾不會影響主事務,主事務回滾會將巢狀事務一起回滾。主事務提交巢狀事務也會跟著提交。

問一個面試官可能會問到的問題,我們知道多條SQL語句開啟的時候,能保證全部成功、或者全部失敗。那麼單條SQL語句有沒有事務呢
其實每個語句都是原子性的,他們被隱式的加入了 BEGIN; START TRANSACTION 開啟事務,並COMMIT;
就好像:

BEGIN;
UPDATE BANK CMBC SET BALANCE = BALANCE + 100000 WHERE USER_NAME = 'A的CMBC銀行賬戶';
COMMIT;
# 如果在語句執行期間發生錯誤,則會回滾該語句。
# 但是如果每個語句都這麼寫,挺麻煩的。所以在事務裡有一個概念叫做自動提交設定!
# 我們每個單語句都會自動提交的,可以自行關閉自動提交!預設是開啟的,這個也區別於全域性global和對談session
show session VARIABLES like 'autocommit'; --查詢自動開啟提交
show global variables like 'autocommit'; --查詢自動開啟提交
set SESSION autocommit=0; --關閉自動提交

總結:資料庫的事務都是為了解決這種業務場景出現的一門技術,為了保證多個SQL語句,要麼全部執行成功,要麼全部執行失敗。

事務的四大特性是什麼?

原子性

一個事務必須被視為一個不可分割的最小單元,整個事務中的操作要麼全部提交成功,要麼全部失敗回滾,對於一個事務來說,不可能只執行其中的一部分操作。

一致性

資料庫總是由一個一致性狀態轉換到另外一個一致性狀態。在前面的例子中,一致性確保了,即使在執行第三條第四條預計之間系統崩潰了,CMBC賬戶中也不會損失10W,要不然A要哭死,如果是系統崩潰最終事務沒有提交,所有事務中所作的修改也不會儲存到資料庫中。

永續性

俗話說就是保證及時落盤;
永續性是為了保證斷點等異常的情況,還能保證我們commit的資料不丟失並且不會回滾
不會出現我commit之後,重啟後又被回滾了!

剛才寫了有個undolog能保證原子性,同樣的,也有個redolog(重做紀錄檔)去保證特殊情況的資料丟失!
redolog會記錄每次事務的執行語句!當發生斷電等比較不可控的因素後,能根據redolog進行資料恢復!!!

隔離性

一個事務所作的修改在最終提交之前,對其他事務是不可見的。在前面的例子中,我們執行完第三條語句,第四條語句還沒成功執行的時候,事務尚未提交。這個時候去看我們ACMBC中的賬號還有10W,如果這個時候去取錢是不可以的,要等待事務提交了才可以。

剛才我們所看到的,是不是都是一個人或者說是一個執行緒的問題?
假如我們有很高的並行量,如果有多個事務同時操作同一條資料,會導致什麼?
事務因並行出現的問題有哪些?可以檢視另一篇文章
連結: 

到此這篇關於MySQL的事務特性概念梳理總結的文章就介紹到這了,更多相關MySQL事務內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com