MySQL事務(wù)的概念以及處理方式

MySQL事務(wù)主要用來處理數(shù)據(jù)量大、數(shù)據(jù)復(fù)雜度高的數(shù)據(jù)操作,最經(jīng)典的使用場景是銀行的轉(zhuǎn)賬:需要先從銀行賬戶A中取出錢,然后再存入銀行賬戶B中,如果中間出現(xiàn)問題,而沒有事務(wù)的保證,那么就會出現(xiàn)B收不到錢,而A支出錢又回不到自己的賬戶的嚴(yán)重問題,那么有了事務(wù)機(jī)制,這個問題就解決了。

定義

事務(wù)(transaction) :全有或全無的操作,是幾個操作組合要么全部發(fā)生要么全部不發(fā)生的工作單元。

事務(wù)的 ACID 特性

在軟件開發(fā)中,一般用一個術(shù)語描述事務(wù):ACID 。ACID 表示 4 個特性。

  • Atomic 原子性:確保事務(wù)中的所有操作全部發(fā)生或全部不發(fā)生。如果所有的活動都成功了,事務(wù)也就成功了。如果任意一個活動失敗了,整個事務(wù)也失敗回滾了。
  • Consistent 一致性:一旦事務(wù)完成(不管成功還是失敗),系統(tǒng)必須確保它所建模的業(yè)務(wù)處于一致的狀態(tài)?,F(xiàn)實的數(shù)據(jù)不應(yīng)該被損壞。
  • Isolated 隔離性:多個用戶對相同的數(shù)據(jù)進(jìn)行操作,每個用戶的操作不會與其他用戶糾纏在一起。避免發(fā)生同步讀寫相同數(shù)據(jù)的事情(注意的是,隔離性往往涉及到鎖定數(shù)據(jù)庫的行或表,會犧牲速度)
  • Durable 持久性:事務(wù)完成后結(jié)果應(yīng)該持久化,能從任何系統(tǒng)崩潰中恢復(fù)過來。一般就是將結(jié)果存儲到數(shù)據(jù)庫中。

當(dāng)任意一個步驟失敗時,所有步驟的操作結(jié)果都會被取消,從而保證了事務(wù)的原子性 。原子性 通過保證系統(tǒng)數(shù)據(jù)永遠(yuǎn)不會處于不一致或部分完成的狀態(tài)來確保一致性 。隔離性同樣確保了一致性 。最后,所有結(jié)果是持久化 的,提交到數(shù)據(jù)存儲中。在發(fā)生系統(tǒng)崩潰或其他災(zāi)難性事情的時候,不用擔(dān)心事務(wù)的結(jié)果丟失。

事務(wù)的隔離

1. 并發(fā)時遇到的問題

在事務(wù)并發(fā)操作時,經(jīng)常出現(xiàn)一些問題,這些問題可用幾個術(shù)語名詞描述:

  • 臟讀
    一個事務(wù)讀取了另一個事務(wù)并發(fā)寫的未提交的數(shù)據(jù),比如:事務(wù)A讀取了事務(wù)B寫入的數(shù)據(jù),但是B事務(wù)并未提交,后來其撤銷了修改,此時事務(wù)A就讀取了不該讀取的數(shù)據(jù)。
  • 幻讀
    一個事務(wù)重復(fù)讀取數(shù)據(jù),在獲得的數(shù)據(jù)行中發(fā)現(xiàn)某些數(shù)據(jù)是其它事務(wù)最近操作的數(shù)據(jù),比如:事務(wù)A反復(fù)執(zhí)行查詢語句查詢數(shù)據(jù)表,而這時另一事務(wù)B正在操作該表,恰好的是事務(wù)B操作的數(shù)據(jù)正符合事務(wù)A查詢的條件,而事務(wù)A再讀取時,發(fā)現(xiàn)結(jié)果集發(fā)生了變化,這在并發(fā)事務(wù)時經(jīng)常出現(xiàn)。
  • 不可重復(fù)讀
    一個事務(wù)重復(fù)讀取之前讀取過的數(shù)據(jù),后發(fā)現(xiàn)讀取的數(shù)據(jù)被另一個事務(wù)所修改,比如:事務(wù)A反復(fù)讀取指定的數(shù)據(jù),而此時事務(wù)B正好操作該數(shù)據(jù),當(dāng)事務(wù)A再次查詢時,發(fā)現(xiàn)之前讀取的數(shù)據(jù)已經(jīng)變化。
    Note: 上面事務(wù)并發(fā)出現(xiàn)的問題,可以通過設(shè)置事務(wù)的隔離來處理,但不能完全依賴事務(wù)隔離,而是應(yīng)該在應(yīng)用程序中恰當(dāng)?shù)氖褂面i來控制并發(fā)訪問,兩者的結(jié)合是解決的問題關(guān)鍵。

2. 事務(wù)的隔離級別

事務(wù)隔離級別分為4種:

隔離級別 含義 可能導(dǎo)致
ISOLATION_DEFAULT 使用后端數(shù)據(jù)庫默認(rèn)的隔離級別 稍微長一點的文本
ISOLATAION_READ_UNCOMMITTED 未提交讀 允許讀取尚未提交的數(shù)據(jù)變更 臟讀、不可重復(fù)讀、幻讀
ISOLATION_READ_COMMITTED 已提交讀 允許讀取并發(fā)事務(wù)已經(jīng)提交的數(shù)據(jù) 不可重復(fù)讀、幻讀
ISOLATION_REPEATABLE_READ 可重復(fù)讀 對同一字段的多次讀取結(jié)果是一致的,除非數(shù)據(jù)是被本事務(wù)自己所修改 幻讀
ISOLATION_SERIALIZABLE 可串行化 完成服從 ACID 隔離級別,確保阻止臟讀、不可重復(fù)讀、幻讀。這是最慢的事務(wù)隔離級別,因為它通常是通過完全鎖定事務(wù)相關(guān)的數(shù)據(jù)庫來實現(xiàn)的

MySQL 事務(wù)

MySQL 數(shù)據(jù)庫中,并不是所有引擎都支持事務(wù),常用的引擎 InnoDB 和 MyISAM 中僅有 InnoDB 支持事務(wù)。
MySQL 一般過程:

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

START TRANSACTION;
    SAVEPOINT step0;
    INSERT INTO new_student (name, age) VALUES ('aaa', 1),('bbb',2); 
    INSERT INTO new_student (name, age) VALUES ('ccc', 3),('ddd',4);
    
    SAVEPOINT step1;
    UPDATE new_student SET age = 100 WHERE name = '張三';

    ROLLBACK TO step1;

事務(wù)語法

  • SET TRANSACTION:用來設(shè)置事務(wù)的隔離級別。InnoDB 存儲引擎提供事務(wù)的隔離級別有 READ UNCOMMITTED 、READ COMMITTED 、REPEATABLE READ 和 SERIALIZABLE 。
  • BEGIN 或START TRANSACTION:顯示地開啟一個事務(wù)。
  • SAVEPOINT <identifier>:SAVEPOINT 允許在事務(wù)中創(chuàng)建一個保存點,一個事務(wù)中可以有多個SAVEPOINT。
  • RELEASE SAVEPOINT <identifier>:刪除一個事務(wù)的保存點,當(dāng)沒有指定的保存點時,執(zhí)行該語句會拋出一個異常。
  • COMMIT:也可以使用COMMIT WORK ,不過二者是等價的。COMMIT 會提交事務(wù),并使已對數(shù)據(jù)庫進(jìn)行的所有修改稱為永久性的。
  • ROLLBACK:有可以使用ROLLBACK WORK ,不過二者是等價的。回滾會結(jié)束用戶的事務(wù),并撤銷正在進(jìn)行的所有未提交的修改。
  • ROLLBACK TO <identifier>:把事務(wù)回滾到標(biāo)記點。

1. 設(shè)置事務(wù)隔離級別

在編寫事務(wù)時,第一步是要確定事務(wù)的隔離級別是什么。使用以下語法設(shè)置:

SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL 
{READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
  • 默認(rèn)為空(不帶 SESSION 和 GLOBAL):為下一個(未開始)事務(wù)設(shè)置隔離級別。
  • GLOBAL:語句在全局對從那點開始創(chuàng)建的所有新連接(除了不存在的連接)設(shè)置默認(rèn)事務(wù)級別。你需要SUPER權(quán)限來做這個。
  • SESSION:為將來在當(dāng)前連接上執(zhí)行的事務(wù)設(shè)置默認(rèn)事務(wù)級別。 任何客戶端都能自由改變會話隔離級別(甚至在事務(wù)的中間),或者為下一個事務(wù)設(shè)置隔離級別。

2. 開始事務(wù)

開始一個 MySQL 的事務(wù)有兩種方法:

  • 用 BEGIN 或START TRANSACTION顯示地開啟一個事務(wù)。當(dāng)遇到 COMMIT 或 ROLLBACK 時,結(jié)束該事務(wù)。
  • 用 SET 來改變 MySQL 的自動提交模式。MySQL 默認(rèn)是自動提交的,但可以通過 SET autocommit = 0, 禁止自動提交。但注意當(dāng)你用 SET autocommit = 0的時候,以后所有的SQL都將做為事務(wù)處理,直到你用 COMMIT 確認(rèn)或 ROLLBACK 結(jié)束,當(dāng)結(jié)束這個事務(wù)的同時也開啟了個新的事務(wù)!按第一種方法只將當(dāng)前的作為一個事務(wù)!

3. 設(shè)置以及釋放 SAVEPOINT

保留點 SAVEPOINT 是為事務(wù)在執(zhí)行過程中提供一個備份。當(dāng)事務(wù)龐大時,保留點就顯得格外有效。
一般的 ROLLBACK 是回滾整個事務(wù),而使用 ROLLBACK TO SAVEPOINT 可以指定回滾到具體某一步。一來省去很多保留點之前的操作,二來更為靈活。
釋放保留點 RELEASE SAVEPOINT <identifier> 是釋放 SAVEPOINT ,保留點在事務(wù)處理完成后(無論是 COMMIT 或 ROLLBACK )就會自動釋放,無需自己釋放。

4. 回滾 ROLLBACK

回滾就是恢復(fù)到事務(wù)執(zhí)行之前,或者是恢復(fù)到 SAVEPOINT 所指向的某一步。
但是,并不是所有的 SQL 命令都是可以回滾的。有些 SQL 命令是包含隱式提交的,則無法回滾。具體有:

  • DDL語句:ALTER DATABASE 、ALTER EVENT 、ALTER PROCEDURE 、ALTER TABLE 、ALTER VIEW 、CREATE TABLE 、DROP TABLE 、RENAME TABLE 、TRUNCATE TABLE 等;
  • 修改 MySQL 架構(gòu)的語句:CREATE USER 、DROP USER 、GRANT 、RENAME USER 、REVOKE 、SET PASSWORD ;
  • 管理語句:ANALYZE TABLE 、CACHE INDEX 、CHECK TABLE 、LOAD INDEX INTO CACHE 、OPTIMIZE TABLE 、REPAIR TABLE 等。

參考鏈接:http://m.itdecent.cn/p/3a73cee85b6d
https://blog.csdn.net/why_2012_gogo/article/details/50953747

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容