MySQL 事務(wù)處理

Q:什么是事務(wù)?
A:指的是一組 SQL 語(yǔ)句或者一個(gè)執(zhí)行單位,要么全部執(zhí)行成功,提交到數(shù)據(jù)庫(kù),要么中間出錯(cuò)全部回滾,不影響數(shù)據(jù)庫(kù)。

Q:事務(wù)的用途有哪些?
A:①、確保尚未全部完成的操作不會(huì)影響到數(shù)據(jù)庫(kù),以致不會(huì)讓數(shù)據(jù)庫(kù)處于部分更新(不一致)狀態(tài);②、確保在操作某個(gè)數(shù)據(jù)行(MySQL 會(huì)對(duì)涉及到的資源進(jìn)行鎖定)時(shí),不會(huì)被其他客戶端修改。

Q:事務(wù)的特性有哪些?
A:具有 ACID 四種特性。
①、Atomic(原子性):構(gòu)成事務(wù)的所有語(yǔ)句是一個(gè)獨(dú)立的邏輯單元,也就是你不能只執(zhí)行所有語(yǔ)句中的一部分語(yǔ)句。
②、Consistent(一致性):數(shù)據(jù)庫(kù)在事務(wù)的執(zhí)行前后必須是一致的。也就是說(shuō)一個(gè)表中的 ID ,必須在另一個(gè)表中找到,否則回滾。
③、Isolated(獨(dú)立性):事務(wù)之間不應(yīng)該相互影響,也就是在并發(fā)執(zhí)行時(shí),事務(wù)能夠挨個(gè)執(zhí)行。
④、Durable(持久性):當(dāng)事務(wù)執(zhí)行成功完成時(shí),會(huì)永久性地記錄到數(shù)據(jù)庫(kù)中。

注意:要想使用事務(wù),就必須選用一種支持事務(wù)處理的存儲(chǔ)引擎。如 InnoDB。

利用事務(wù)保證語(yǔ)句安全執(zhí)行

MySQL 默認(rèn)是自動(dòng)提交到數(shù)據(jù)庫(kù)(永久性保存)

-- 查看執(zhí)行事務(wù)的方法:1:開啟自動(dòng)提交 0:禁用自動(dòng)提交
SELECT @@global.autocommit;
SELECT @@session.autocommit;
SELECT @@autocommit;

兩種執(zhí)行事務(wù)的方法:
1、start transaction(或 begin)語(yǔ)句

-- ①、掛起自動(dòng)提交模式,開啟一個(gè)新的事務(wù)。
START TRANSACTION;
-- ②、執(zhí)行構(gòu)成本次事務(wù)的各條 SQL 語(yǔ)句
INSERT INTO t SET name = 'zhangsan';
INSERT INTO t SET name = 'lisi';
-- ③、用 COMMIT 語(yǔ)句永久性保存這些更改 或者 用 ROLLBACK 語(yǔ)句撤銷所有更改。
COMMIT;
SELECT * FROM t;

注意:它是開啟一個(gè)新的事務(wù),在事務(wù)被提交或回滾之后,該模式將恢復(fù)到開始本次事務(wù)的 START TRANSACTION 語(yǔ)句被執(zhí)行之前的狀態(tài)(如果自動(dòng)提交模式原來(lái)是激活的,結(jié)束事務(wù)將讓你回到自動(dòng)提交模式;如果它原來(lái)是禁用的,結(jié)束當(dāng)前事務(wù)將開始下一個(gè)事務(wù))

2、SET 語(yǔ)句直接操作自動(dòng)提交模式的狀態(tài)

-- ①、禁用自動(dòng)提交
SET AUTOCOMMIT = 0;
-- ②、執(zhí)行構(gòu)成本次事務(wù)的各條 SQL 語(yǔ)句
INSERT INTO t SET name = 'zhangsan';
INSERT INTO t SET name = 'lisi';
-- ③、用 COMMIT 語(yǔ)句永久性保存這些更改 或者 用 ROLLBACK 語(yǔ)句撤銷所有更改。
COMMIT;
-- ④、開啟自動(dòng)提交
SET AUTOCOMMIT = 1;

注意:是在當(dāng)前 session 禁用自動(dòng)提交事物。

使用事務(wù)保存點(diǎn)

MySQL 可以對(duì)事物進(jìn)行部分回滾(即回滾到保存點(diǎn))。

CREATE TABLE t(i INT) ENGINE = InnoDB;
START TRANSACTION ;
INSERT INTO t VALUES (1);
SAVEPOINT my_savepoint; -- 保存點(diǎn)
INSERT INTO t VALUES (2);
ROLLBACK TO SAVEPOINT my_savepoint; -- 回滾到保存點(diǎn)
INSERT INTO t VALUES (3);
COMMIT ;
SELECT * FROM t; -- 1 、 3
事務(wù)隔離

在數(shù)據(jù)庫(kù)操作中,為了有效保證并發(fā)讀取數(shù)據(jù)的正確性,提出的事務(wù)隔離級(jí)別。
在多個(gè)事務(wù)并發(fā)操作的過(guò)程中,如果控制不好隔離級(jí)別,就有可能產(chǎn)生臟讀、不可重復(fù)讀或者幻讀等讀現(xiàn)象。

  • 臟讀:一個(gè)事務(wù)讀取到了另一個(gè)事務(wù)未提交的數(shù)據(jù)操作結(jié)果。危險(xiǎn)之處:很可能所有的操作都被回滾。
  • 不可重復(fù)讀:同一個(gè)事務(wù)使用同一條 SELECT 語(yǔ)句在每次讀取時(shí)得到的結(jié)果都不一樣
  • 幻影行一個(gè)事務(wù)突然看到一個(gè)以前沒(méi)有見過(guò)的數(shù)據(jù)行。某個(gè)事務(wù)在 SELECT 之后,另一個(gè)事務(wù)插入一條新的數(shù)據(jù)行,如果第一個(gè)事務(wù)再執(zhí)行同樣的一條 SELECT 語(yǔ)句,則可能會(huì)看到這個(gè)新增行,而它其實(shí)是一個(gè)幻影。

為了解決以上這些問(wèn)題,InnoDB 存儲(chǔ)引擎提供了 4 種事務(wù)隔離級(jí)別

  • READ UNCOMMITTED:允許某個(gè)事務(wù)看到其他事務(wù)尚未提交的行修改。
  • READ COMMITTED:只允許某個(gè)事務(wù)看到其他事務(wù)已經(jīng)提交的行修改。
  • REPEATABLE READ:如果某個(gè)事務(wù)兩次執(zhí)行同一條 SELECT 語(yǔ)句,其結(jié)果是可重復(fù)的。也就是說(shuō),即使有其他事務(wù)在同時(shí)插入或修改行,這個(gè)事務(wù)所看到的結(jié)果也是一樣的。
  • SERIALIZABLE:對(duì)于某個(gè)事務(wù)正在查看的行,只有等到該事務(wù)完成才能被其他事務(wù)所修改

InnoDB 存儲(chǔ)引擎默認(rèn)的隔離級(jí)別REPEATABLE READ。
修改它的兩種方式:①、在服務(wù)器啟動(dòng)時(shí)使用 --transaction-isolation 選項(xiàng);②、在服務(wù)器運(yùn)行時(shí)使用 SET TRANSACTION 語(yǔ)句

-- 查看隔離級(jí)別
select @@global.tx_isolation;
select @@session.tx_isolation;
SELECT @@tx_isolation;

-- 改變?nèi)指綦x級(jí)別,作用于后續(xù)的所有客戶端連接
SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;
-- 改變當(dāng)前會(huì)話里的所有事務(wù)的隔離級(jí)別
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;
-- 改變下一個(gè)事務(wù)的隔離級(jí)別
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;

最后:四種事務(wù)隔離級(jí)別從隔離程度上越來(lái)越高,但同時(shí)在并發(fā)性上也就越來(lái)越低。我們應(yīng)該在開發(fā)過(guò)程中根據(jù)業(yè)務(wù)需要選擇最合適的隔離級(jí)別。

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

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