SQL必知必會(事務(wù)處理)

事務(wù)的特性:ACID

事務(wù)的特性:要么完全執(zhí)行,要么都不執(zhí)行。不過要對事務(wù)進(jìn)行更深一步的理解殊霞,還要從事務(wù)的 4 個特性說起罐农,這 4 個特性用英文字母來表達(dá)就是 ACID。

  • 1. A譬淳,也就是原子性(Atomicity)。原子的概念就是不可分割奋单,你可以把它理解為組成物質(zhì)的基本單位宛畦,也是我們進(jìn)行數(shù)據(jù)處理操作的基本單位瘸洛。
  • 2. C,就是一致性(Consistency)刃永。一致性指的就是數(shù)據(jù)庫在進(jìn)行事務(wù)操作后货矮,會由原來的一致狀態(tài),變成另一種一致的狀態(tài)斯够。也就是說當(dāng)事務(wù)提交后囚玫,或者當(dāng)事務(wù)發(fā)生回滾后,數(shù)據(jù)庫的完整性約束不能被破壞读规。
  • 3. I抓督,就是隔離性(Isolation)。它指的是每個事務(wù)都是彼此獨立的束亏,不會受到其他事務(wù)的執(zhí)行影響铃在。也就是說一個事務(wù)在提交之前,對其他事務(wù)都是不可見的碍遍。
  • 4. 最后一個 D定铜,指的是持久性(Durability)。事務(wù)提交之后對數(shù)據(jù)的修改是持久性的怕敬,即使在系統(tǒng)出故障的情況下揣炕,比如系統(tǒng)崩潰或者存儲介質(zhì)發(fā)生故障,數(shù)據(jù)的修改依然是有效的东跪。因為當(dāng)事務(wù)完成畸陡,數(shù)據(jù)庫的日志就會被更新,這時可以通過日志虽填,讓系統(tǒng)恢復(fù)到最后一次成功的更新狀態(tài)丁恭。

ACID 可以說是事務(wù)的四大特性,在這四個特性中斋日,原子性是基礎(chǔ)牲览,隔離性是手段,一致性是約束條件桑驱,而持久性是我們的目的竭恬。原子性和隔離性比較好理解,這里我講下對一致性的理解(國內(nèi)很多網(wǎng)站上對一致性的闡述有誤熬的,具體你可以參考 Wikipedia 對Consistency的闡述)痊硕。

我之前講到過數(shù)據(jù)表的 7 種常見約束(對應(yīng) 04 篇)。這里指的一致性本身是由具體的業(yè)務(wù)定義的押框,也就是說岔绸,任何寫入數(shù)據(jù)庫中的數(shù)據(jù)都需要滿足我們事先定義的約束規(guī)則。

事務(wù)的控制

當(dāng)我們了解了事務(wù)的特性后,再來看下如何使用事務(wù)盒揉。我們知道 Oracle 是支持事務(wù)的晋被,而在 MySQL 中,則需要選擇適合的存儲引擎才可以支持事務(wù)刚盈。如果你使用的是 MySQL羡洛,可以通過 SHOW ENGINES 命令來查看當(dāng)前 MySQL 支持的存儲引擎都有哪些,以及這些存儲引擎是否支持事務(wù)藕漱。

你能看出在 MySQL 中欲侮,InnoDB 是支持事務(wù)的,而 MyISAM 存儲引擎不支持事務(wù)肋联。

看到這里威蕉,我們已經(jīng)對事務(wù)有了一定的了解,現(xiàn)在我們再來看下事務(wù)的常用控制語句都有哪些橄仍。

  • 1. START TRANSACTION 或者 BEGIN韧涨,作用是顯式開啟一個事務(wù)。
  • 2. COMMIT:提交事務(wù)侮繁。當(dāng)提交事務(wù)后虑粥,對數(shù)據(jù)庫的修改是永久性的。
  • 3. ROLLBACK 或者 ROLLBACK TO [SAVEPOINT],意為回滾事務(wù)宪哩。意思是撤銷正在進(jìn)行的所有沒有提交的修改舀奶,或者將事務(wù)回滾到某個保存點。
  • 4. SAVEPOINT:在事務(wù)中創(chuàng)建保存點斋射,方便后續(xù)針對保存點進(jìn)行回滾。一個事務(wù)中可以存在多個保存點但荤。
  • 5. RELEASE SAVEPOINT:刪除某個保存點罗岖。
  • 6. SET TRANSACTION,設(shè)置事務(wù)的隔離級別腹躁。

需要說明的是桑包,使用事務(wù)有兩種方式,分別為隱式事務(wù)和顯式事務(wù)纺非。隱式事務(wù)實際上就是自動提交哑了,Oracle 默認(rèn)不自動提交,需要手寫 COMMIT 命令烧颖,而 MySQL 默認(rèn)自動提交弱左,當(dāng)然我們可以配置 MySQL 的參數(shù):

mysql> set autocommit =0;  // 關(guān)閉自動提交
mysql> set autocommit =1;  // 開啟自動提交

我們看下在 MySQL 的默認(rèn)狀態(tài)下,下面這個事務(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;

在這個事務(wù)中炕淮,整個 SQL 一共執(zhí)行了 2 個事務(wù)拆火,第一個是插入“關(guān)羽”,提交后執(zhí)行成功,第二個是插入兩次“張飛”们镜,這里需要注意的是币叹,我們將 name 設(shè)置為了主鍵,也就是說主鍵的值是唯一的模狭,那么第二次插入“張飛”時就會產(chǎn)生錯誤颈抚,然后執(zhí)行 ROLLBACK 相當(dāng)于對事務(wù)進(jìn)行了回滾,所以我們看到最終結(jié)果只有一行數(shù)據(jù)嚼鹉,也就是第一個事務(wù)執(zhí)行之后的結(jié)果贩汉,即“關(guān)羽”。

那么如果我們進(jìn)行下面的操作又會怎樣呢反砌?

CREATE TABLE testn(name varchar(255), PRIMARY KEY (name)) ENGINE=InnoDB;
BEGIN;
INSERT INTO testn SELECT '關(guān)羽';
COMMIT;
INSERT INTO testn SELECT '張飛';
INSERT INTO testn SELECT '張飛';
ROLLBACK;
SELECT * FROM testn;

你能看到這次數(shù)據(jù)是 2 行雾鬼,上一次操作我把兩次插入“張飛”放到一個事務(wù)里,而這次操作它們不在同一個事務(wù)里宴树,那么對于 MySQL 來說策菜,默認(rèn)情況下這實際上就是兩個事務(wù),因為在 autocommit=1 的情況下酒贬,MySQL 會進(jìn)行隱式事務(wù)又憨,也就是自動提交,因此在進(jìn)行第一次插入“張飛”后锭吨,數(shù)據(jù)表里就存在了兩行數(shù)據(jù)蠢莺,而第二次插入“張飛”就會報錯:1062 - Duplicate entry '張飛' for key 'PRIMARY'

最后我們在執(zhí)行 ROLLBACK 的時候零如,實際上事務(wù)已經(jīng)自動提交了躏将,就沒法進(jìn)行回滾了。

同樣的我們再來看下這段代碼考蕾,你又能發(fā)現(xià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;

你能看到還是相同的 SQL 代碼,只是我在事務(wù)開始之前設(shè)置了SET @@completion_type = 1;肖卧,結(jié)果就和我們第一次處理的一樣蚯窥,只有一個“關(guān)羽”。這是為什么呢塞帐?

這里我講解下 MySQL 中 completion_type 參數(shù)的作用拦赠,實際上這個參數(shù)有 3 種可能

  • 1. completion=0,這是默認(rèn)情況葵姥。也就是說當(dāng)我們執(zhí)行 COMMIT 的時候會提交事務(wù)荷鼠,在執(zhí)行下一個事務(wù)時,還需要我們使用 START TRANSACTION 或者 BEGIN 來開啟榔幸。
  • 2. completion=1颊咬,這種情況下务甥,當(dāng)我們提交事務(wù)后,相當(dāng)于執(zhí)行了 COMMIT AND CHAIN喳篇,也就是開啟一個鏈?zhǔn)绞聞?wù)敞临,即當(dāng)我們提交事務(wù)之后會開啟一個相同隔離級別的事務(wù)(隔離級別會在下一節(jié)中進(jìn)行介紹)。
  • 3. completion=2麸澜,這種情況下 COMMIT=COMMIT AND RELEASE挺尿,也就是當(dāng)我們提交后,會自動與服務(wù)器斷開連接炊邦。

在上面這段代碼里编矾,我使用了 completion=1,也就是說當(dāng)我提交之后馁害,相當(dāng)于在下一行寫了一個 START TRANSACTION 或 BEGIN窄俏。這時兩次插入“張飛”會被認(rèn)為是在同一個事務(wù)之內(nèi)的操作,那么第二次插入“張飛”就會導(dǎo)致事務(wù)失敗碘菜,而回滾也將這次事務(wù)進(jìn)行了撤銷凹蜈,所以你能看到的結(jié)果就只有一個“關(guān)羽”。

當(dāng)我們設(shè)置 autocommit=0 時忍啸,不論是否采用 START TRANSACTION 或者 BEGIN 的方式來開啟事務(wù)仰坦,都需要用 COMMIT 進(jìn)行提交,讓事務(wù)生效计雌,使用 ROLLBACK 對事務(wù)進(jìn)行回滾悄晃。

當(dāng)我們設(shè)置 autocommit=1 時,每條 SQL 語句都會自動進(jìn)行提交凿滤。
不過這時妈橄,如果你采用 START TRANSACTION 或者 BEGIN 的方式來顯式地開啟事務(wù),那么這個事務(wù)只有在 COMMIT 時才會生效翁脆,在 ROLLBACK 時才會回滾眷细。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市鹃祖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌普舆,老刑警劉巖恬口,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異沼侣,居然都是意外死亡祖能,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進(jìn)店門蛾洛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來养铸,“玉大人雁芙,你說我怎么就攤上這事〕” “怎么了兔甘?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鳞滨。 經(jīng)常有香客問我洞焙,道長,這世上最難降的妖魔是什么拯啦? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任澡匪,我火速辦了婚禮,結(jié)果婚禮上褒链,老公的妹妹穿的比我還像新娘唁情。我一直安慰自己,他們只是感情好甫匹,可當(dāng)我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布甸鸟。 她就那樣靜靜地躺著,像睡著了一般赛惩。 火紅的嫁衣襯著肌膚如雪哀墓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天喷兼,我揣著相機與錄音篮绰,去河邊找鬼。 笑死季惯,一個胖子當(dāng)著我的面吹牛吠各,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播勉抓,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼贾漏,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了藕筋?” 一聲冷哼從身側(cè)響起纵散,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎隐圾,沒想到半個月后伍掀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡暇藏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年蜜笤,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盐碱。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡把兔,死狀恐怖沪伙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情县好,我是刑警寧澤围橡,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站聘惦,受9級特大地震影響某饰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜善绎,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一黔漂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧禀酱,春花似錦炬守、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至曹洽,卻和暖如春鳍置,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背送淆。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工税产, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人偷崩。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓辟拷,卻偏偏與公主長得像,于是被迫代替她去往敵國和親阐斜。 傳聞我的和親對象是個殘疾皇子衫冻,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,629評論 2 354

推薦閱讀更多精彩內(nèi)容