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í)別。