目錄鏈接:http://www.reibang.com/p/2c104aaadb03
事務(wù)的特性
事務(wù)的 4 個(gè)特性說起峻黍, 這 4 個(gè)特性英文字母來表達(dá)就是 ACID株婴。
A细疚, 也就是原子性(Atomicity) 茄唐。 原子的概念就是不可分割芋肠, 你可以把它理解為組成物質(zhì)的基本單位, 也是我們進(jìn)行數(shù)據(jù)處理操作的基本單位
C幽崩, 就是一致性(Consistency) 苦始。一致性指的就是數(shù)據(jù)庫在進(jìn)行事務(wù)操作后, 會(huì)由原來的一致狀態(tài)慌申, 變成另一種一致的狀態(tài)陌选。 也就是說當(dāng)事務(wù)提交后, 或者當(dāng)事務(wù)發(fā)生回滾后蹄溉, 數(shù)據(jù)庫的完整性約束不能被破壞咨油。
I, 就是隔離性(Isolation) 柒爵。 它指的是每個(gè)事務(wù)都是彼此獨(dú)立的役电, 不會(huì)受到其他事務(wù)的執(zhí)行影響。 也就是說一個(gè)事務(wù)在提交之前棉胀, 對其他事務(wù)都是不可見的法瑟。
最后一個(gè) D, 指的是持久性(Durability) 唁奢。 事務(wù)提交之后對數(shù)據(jù)的修改是持久性的霎挟, 即使在系統(tǒng)出故障的情況下, 比如系統(tǒng)崩潰或者存儲(chǔ)介質(zhì)發(fā)生故障麻掸, 數(shù)據(jù)的修改依然是有效的酥夭。
ACID 可以說是事務(wù)的四大特性, 在這四個(gè)特性中论笔, 原子性是基礎(chǔ)采郎, 隔離性是手段, 一致性是約束條件狂魔,持久性是我們的目的蒜埋。
事務(wù)的控制
Oracle 是支持事務(wù)的, 在MySQL 中最楷, 則需要選擇適合的存儲(chǔ)引擎才可以支持事務(wù)整份。可以通過SHOW ENGINES 命令來查看當(dāng)前 MySQL 支持的存儲(chǔ)引擎都有哪些籽孙, 以及這些存儲(chǔ)引擎是否支持事務(wù)烈评。
常用控制語句
- START TRANSACTION 或者 BEGIN, 作用是顯式開啟一個(gè)事務(wù)犯建。
- COMMIT:提交事務(wù)讲冠。 當(dāng)提交事務(wù)后, 對數(shù)據(jù)庫的修改是永久性的适瓦。
- ROLLBACK 或者 ROLLBACK TO [SAVEPOINT]竿开, 意為回滾事務(wù)谱仪。 意思是撤銷正在進(jìn)行的所有沒有提交的修改, 或者將事務(wù)回滾到某個(gè)保存點(diǎn)否彩。
- SAVEPOINT:在事務(wù)中創(chuàng)建保存點(diǎn)疯攒,方便后續(xù)針對保存點(diǎn)進(jìn)行回滾。 一個(gè)事務(wù)中可以存在多個(gè)保存點(diǎn)列荔。
- RELEASE SAVEPOINT:刪除某個(gè)保存點(diǎn)敬尺。
- SET TRANSACTION, 設(shè)置事務(wù)的隔離級(jí)別贴浙。
使用事務(wù)有兩種方式砂吞, 分別為隱式事務(wù)和顯式事務(wù)。 隱式事務(wù)實(shí)際上就是自動(dòng)提交悬而, Oracle 默認(rèn)不自動(dòng)提交呜舒, 需要手寫 COMMIT 命令锭汛, 而 MySQL 默認(rèn)自動(dòng)提交笨奠, 當(dāng)然我們可以配置 MySQL 的參數(shù):
mysql> set autocommit =0; // 關(guān)閉自動(dòng)提交
mysql> set autocommit =1; // 開啟自動(dòng)提交
在 MySQL 的默認(rèn)狀態(tài)下, 下面這個(gè)事務(wù)最后的處理結(jié)果
CREATE TABLE test(name varchar(255), PRIMARY KEY (name)) ENGINE=InnoDB;
BEGIN;
INSERT INTO test SELECT '關(guān)羽';
COMMIT;
BEGIN;
INSERT INTO test SELECT '張飛';
INSERT INTO test SELECT '張飛';
ROLLBACK;
SELECT * FROM test;
一共執(zhí)行了 2 個(gè)事務(wù)唤殴, 第一個(gè)是插入“關(guān)羽”般婆, 提交后執(zhí)行成功, 第二個(gè)是插入兩次“張飛”朵逝, 需要注意的是蔚袍, 我們將 name 設(shè)置為了主鍵, 也就是說主鍵的值是唯一的配名, 那么第二次插入“張飛”時(shí)就會(huì)產(chǎn)生錯(cuò)誤啤咽, 然后執(zhí)行ROLLBACK 相當(dāng)于對事務(wù)進(jìn)行了回滾, 所以我們看到最終結(jié)果只有一行數(shù)據(jù)渠脉, 也就是第一個(gè)事務(wù)執(zhí)行之后的結(jié)果宇整。
下面的操作又會(huì)怎樣呢?注意插入“張飛”前并沒有BEGIN;
CREATE TABLE test(name varchar(255), PRIMARY KEY (name)) ENGINE=InnoDB;
BEGIN;
INSERT INTO test SELECT '關(guān)羽';
COMMIT;
INSERT INTO test SELECT '張飛';
INSERT INTO test SELECT '張飛';
ROLLBACK;
SELECT * FROM test;
上次操作我把兩次插入“張飛”放到一個(gè)事務(wù)中芋膘, 這次操作它們不在同一個(gè)事務(wù)里鳞青,那么對于 MySQL 來說, 默認(rèn)情況下這實(shí)際上就是兩個(gè)事務(wù)为朋, 因?yàn)樵?autocommit=1 的情況下臂拓, MySQL 會(huì)進(jìn)行隱式事務(wù), 也就是自動(dòng)提交习寸, 因此在進(jìn)行第一次插入“張飛”后胶惰, 數(shù)據(jù)表中就存在了兩個(gè)數(shù)據(jù), 而第二次插入“張飛”就會(huì)報(bào)錯(cuò)霞溪,最后我們在執(zhí)行ROLLBACK 的時(shí)候孵滞, 實(shí)際上事務(wù)已經(jīng)自動(dòng)提交了精钮, 就沒法進(jìn)行回滾了。
再來看下這段代碼:
CREATE TABLE test(name varchar(255), PRIMARY KEY (name)) ENGINE=InnoDB;
SET @@completion_type = 1;
BEGIN;
INSERT INTO test SELECT '關(guān)羽';
COMMIT;
INSERT INTO test SELECT '張飛';
INSERT INTO test SELECT '張飛';
ROLLBACK;
SELECT * FROM test;
事務(wù)開始之前設(shè)置了 SET @@completion_type = 1; 剃斧, 結(jié)果就和我們第一次處理的一樣轨香, 只有一個(gè)“關(guān)羽”。
MySQL 中 completion_type 參數(shù)的作用
completion=0幼东, 這是默認(rèn)情況臂容。 也就是說當(dāng)我們執(zhí)行COMMIT 的時(shí)候會(huì)提交事務(wù), 在執(zhí)行下一個(gè)事務(wù)時(shí)根蟹, 還需要我們使用 STARTTRANSACTION 或者 BEGIN 來開啟脓杉。
completion=1, 這種情況下简逮, 當(dāng)我們提交事務(wù)后球散, 相當(dāng)于執(zhí)行了 COMMIT AND CHAIN,也就是開啟一個(gè)鏈?zhǔn)绞聞?wù)散庶, 即當(dāng)我們提交事務(wù)之后會(huì)開啟一個(gè)相同隔離級(jí)別的事務(wù)蕉堰。
completion=2, 這種情況下 COMMIT=COMMIT AND RELEASE悲龟, 也就是當(dāng)我們提交后屋讶, 會(huì)自動(dòng)與服務(wù)器斷開連接。
使用了 completion=1须教, 也就是說當(dāng)我提交之后皿渗, 相當(dāng)于在下一行寫了一個(gè)START TRANSACTION 或 BEGIN。 這時(shí)兩次插入“張飛”會(huì)被認(rèn)為是在同一個(gè)事務(wù)之內(nèi)的操作轻腺, 那么第二次插入“張飛”就會(huì)導(dǎo)致事務(wù)失敗乐疆, 而回滾也將這次事務(wù)進(jìn)行了撤銷, 所以你能看到的結(jié)果就只有一個(gè)“關(guān)羽”贬养。
當(dāng)我們設(shè)置 autocommit=0 時(shí)挤土, 不論是否采用START TRANSACTION 或者 BEGIN 的方式來開啟事務(wù), 都需要用 COMMIT 進(jìn)行提交煤蚌, 讓事務(wù)生效耕挨, 使用 ROLLBACK 對事務(wù)進(jìn)行回滾。MySQL中尉桩,如果是連續(xù)BEGIN筒占,開啟了第一個(gè)事務(wù),還沒有進(jìn)行COMMIT提交蜘犁,而直接進(jìn)行第二個(gè)事務(wù)的BEGIN翰苫,數(shù)據(jù)庫會(huì)隱式的幫助COMMIT第一個(gè)事務(wù),然后進(jìn)入到第二個(gè)事務(wù)
當(dāng)我們設(shè)置 autocommit=1 時(shí), 每條 SQL 語句都會(huì)自動(dòng)進(jìn)行提交奏窑。不過這時(shí)导披, 如果你采用 START TRANSACTION 或者 BEGIN 的方式來顯式地開啟事務(wù), 那么這個(gè)事務(wù)只有在 COMMIT 時(shí)才會(huì)生效埃唯, 在 ROLLBACK 時(shí)才會(huì)回滾撩匕。
參考資料:
練習(xí)數(shù)據(jù)庫使用 SQL必知必會(huì)專欄(極客時(shí)間)中的作者提供的 王者榮耀數(shù)據(jù)庫以及NBA數(shù)據(jù)庫
練習(xí)系統(tǒng) MySQL Server version: 5.7.26-0ubuntu0.16.04.1 (Ubuntu)
SQL必知必會(huì)專欄(極客時(shí)間)鏈接:
http://gk.link/a/103Sm
《MySQL必知必會(huì)》學(xué)習(xí)筆記(24-29):
http://www.reibang.com/p/ee15e71ab1b8
此篇內(nèi)容:使用游標(biāo)、使用觸發(fā)器墨叛、管理事務(wù)處理止毕、全球化和本地化、安全管理漠趁、數(shù)據(jù)庫維護(hù)
GitHub鏈接:
https://github.com/lichangke/LeetCode
知乎個(gè)人首頁:
https://www.zhihu.com/people/lichangke/
簡書個(gè)人首頁:
http://www.reibang.com/u/3e95c7555dc7
個(gè)人Blog:
https://lichangke.github.io/
歡迎大家來一起交流學(xué)習(xí)