MySQL中事務(wù)概念的簡(jiǎn)潔學(xué)習(xí)教程
事務(wù)是由一步或幾步數(shù)據(jù)庫(kù)操作序列組成邏輯執(zhí)行單元,這系列操作要么全部執(zhí)行,要么全部放棄執(zhí)行。程序和事務(wù)是兩個(gè)不同的概念。一般而言:一段程序中可能包含多個(gè)事務(wù)。
事務(wù)具有四個(gè)特性:原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)和持續(xù)性(Durability)。這四個(gè)特性也簡(jiǎn)稱ACID性。
1)原子性:事務(wù)是應(yīng)用中最小的執(zhí)行單位,就如原子是自然界最小顆粒,具有不可再分的特征一樣。事務(wù)是應(yīng)用中不可再分的最小邏輯執(zhí)行體。
2)一致性:事務(wù)執(zhí)行的結(jié)果,必須使數(shù)據(jù)庫(kù)從一個(gè)一致性狀態(tài),變到另一個(gè)一致性狀態(tài)。當(dāng)數(shù)據(jù)庫(kù)中只包含事務(wù)成功提交的結(jié)果時(shí),數(shù)據(jù)庫(kù)處于一致性狀態(tài)。一致性是通過(guò)原子性來(lái)保證的。
3)隔離性:各個(gè)事務(wù)的執(zhí)行互不干擾,任意一個(gè)事務(wù)的內(nèi)部操作對(duì)其他并發(fā)的事務(wù),都是隔離的。也就是說(shuō):并發(fā)執(zhí)行的事務(wù)之間不能看到對(duì)方的中間狀態(tài),并發(fā)執(zhí)行的事務(wù)之間不能相互影響。
4)持續(xù)性:持續(xù)性也稱為持久性,指事務(wù)一旦提交,對(duì)數(shù)據(jù)所做的任何改變,都要記錄到永久存儲(chǔ)器中,通常是保存進(jìn)物理數(shù)據(jù)庫(kù)。
在關(guān)系型數(shù)據(jù)庫(kù)中,事務(wù)的隔離性分為四個(gè)隔離級(jí)別,在解讀這四個(gè)級(jí)別前先介紹幾個(gè)關(guān)于讀數(shù)據(jù)的概念。
1)臟讀(Dirty Reads):所謂臟讀就是對(duì)臟數(shù)據(jù)(Drity Data)的讀取,而臟數(shù)據(jù)所指的就是未提交的數(shù)據(jù)。也就是說(shuō),一個(gè)事務(wù)正在對(duì)一條記錄做修改,在這個(gè)事務(wù)完成并提交之前,這條數(shù)據(jù)是處于待定狀態(tài)的(可能提交也可能回滾),這時(shí),第二個(gè)事務(wù)來(lái)讀取這條沒(méi)有提交的數(shù)據(jù),并據(jù)此做進(jìn)一步的處理,就會(huì)產(chǎn)生未提交的數(shù)據(jù)依賴關(guān)系。這種現(xiàn)象被稱為臟讀。
2)不可重復(fù)讀(Non-Repeatable Reads):一個(gè)事務(wù)先后讀取同一條記錄,但兩次讀取的數(shù)據(jù)不同,我們稱之為不可重復(fù)讀。也就是說(shuō),這個(gè)事務(wù)在兩次讀取之間該數(shù)據(jù)被其它事務(wù)所修改。
3)幻讀(Phantom Reads):一個(gè)事務(wù)按相同的查詢條件重新讀取以前檢索過(guò)的數(shù)據(jù),卻發(fā)現(xiàn)其他事務(wù)插入了滿足其查詢條件的新數(shù)據(jù),這種現(xiàn)象就稱為幻讀。
事務(wù)四個(gè)隔離級(jí)別對(duì)比:
1)未提交讀(Read Uncommitted):SELECT語(yǔ)句以非鎖定方式被執(zhí)行,所以有可能讀到臟數(shù)據(jù),隔離級(jí)別最低。
2)提交讀(Read Committed):只能讀取到已經(jīng)提交的數(shù)據(jù)。即解決了臟讀,但未解決不可重復(fù)讀。
3)可重復(fù)讀(Repeated Read):在同一個(gè)事務(wù)內(nèi)的查詢都是事務(wù)開(kāi)始時(shí)刻一致的,InnoDB的默認(rèn)級(jí)別。在SQL標(biāo)準(zhǔn)中,該隔離級(jí)別消除了不可重復(fù)讀,但是還存在幻讀。
4)串行讀(Serializable):完全的串行化讀,所有SELECT語(yǔ)句都被隱式的轉(zhuǎn)換成SELECT ... LOCK IN SHARE MODE,即讀取使用表級(jí)共享鎖,讀寫相互都會(huì)阻塞。隔離級(jí)別最高。
隔離級(jí)別對(duì)比表:
數(shù)據(jù)庫(kù)的事務(wù)有下列語(yǔ)句組成:
一組DML(Data Manipulate Language,即數(shù)據(jù)操作語(yǔ)言)經(jīng)過(guò)這組DML修改后數(shù)據(jù)將保持較好的一致性。
一個(gè)DDL(Data Definition Language,即數(shù)據(jù)定義語(yǔ)言)語(yǔ)句。
一個(gè)DCL(Data control Language,即數(shù)據(jù)控制語(yǔ)言)語(yǔ)句。
DDL和DCL語(yǔ)句最多只能有一個(gè),因?yàn)镈DL和DCL語(yǔ)句都會(huì)導(dǎo)致事務(wù)立即提交。
當(dāng)事務(wù)所包含的全部數(shù)據(jù)庫(kù)操作都成功執(zhí)行后,應(yīng)該提交(commit)事務(wù),使這些修改永久生效。
事務(wù)提交有兩種方式:顯式提交和自動(dòng)提交。
(1)顯式提交:使用commit。
(2)自動(dòng)提交:執(zhí)行DDL或DCL,或者程序正常退出。
數(shù)據(jù)庫(kù)事務(wù)傳播級(jí)別,指的是事務(wù)嵌套時(shí),應(yīng)該采用什么策略,即在一個(gè)事務(wù)中調(diào)用別的事務(wù),該怎么辦
假如有一下兩個(gè)事務(wù):
ServiceA { void methodA () { ServiceB . methodB (); } } ServiceB { void methodB () { } }
1 : PROPAGATION_REQUIRED
加入當(dāng)前正要執(zhí)行的事務(wù)不在另外一個(gè)事務(wù)里,那么就起一個(gè)新的事務(wù)
比如說(shuō), ServiceB.methodB 的事務(wù)級(jí)別定義為 PROPAGATION_REQUIRED, 那么由于執(zhí)行 ServiceA.methodA 的時(shí)候,
ServiceA.methodA 已經(jīng)起了事務(wù),這時(shí)調(diào)用 ServiceB.methodB , ServiceB.methodB 看到自己已經(jīng)運(yùn)行在 ServiceA.methodA
的事務(wù)內(nèi)部,就不再起新的事務(wù)。而假如 ServiceA.methodA 運(yùn)行的時(shí)候發(fā)現(xiàn)自己沒(méi)有在事務(wù)中,他就會(huì)為自己分配一個(gè)事務(wù)。
這樣,在 ServiceA.methodA 或者在 ServiceB.methodB 內(nèi)的任何地方出現(xiàn)異常,事務(wù)都會(huì)被回滾。即使 ServiceB.methodB 的事務(wù)已經(jīng)被
提交,但是 ServiceA.methodA 在接下來(lái) fail 要回滾, ServiceB.methodB 也要回滾
2 : PROPAGATION_SUPPORTS
如果當(dāng)前在事務(wù)中,即以事務(wù)的形式運(yùn)行,如果當(dāng)前不再一個(gè)事務(wù)中,那么就以非事務(wù)的形式運(yùn)行
3 : PROPAGATION_MANDATORY
必須在一個(gè)事務(wù)中運(yùn)行。也就是說(shuō),他只能被一個(gè)父事務(wù)調(diào)用。否則,他就要拋出異常
4 : PROPAGATION_REQUIRES_NEW
這個(gè)就比較繞口了。 比如我們?cè)O(shè)計(jì) ServiceA.methodA 的事務(wù)級(jí)別為 PROPAGATION_REQUIRED , ServiceB.methodB 的事務(wù)級(jí)別為 PROPAGATION_REQUIRES_NEW ,
那么當(dāng)執(zhí)行到 ServiceB.methodB 的時(shí)候, ServiceA.methodA 所在的事務(wù)就會(huì)掛起, ServiceB.methodB 會(huì)起一個(gè)新的事務(wù),等待 ServiceB.methodB 的事務(wù)完成以后,
他才繼續(xù)執(zhí)行。他與 PROPAGATION_REQUIRED 的事務(wù)區(qū)別在于事務(wù)的回滾程度了。因?yàn)?ServiceB.methodB 是新起一個(gè)事務(wù),那么就是存在
兩個(gè)不同的事務(wù)。如果 ServiceB.methodB 已經(jīng)提交,那么 ServiceA.methodA 失敗回滾, ServiceB.methodB 是不會(huì)回滾的。如果 ServiceB.methodB 失敗回滾,
如果他拋出的異常被 ServiceA.methodA 捕獲, ServiceA.methodA 事務(wù)仍然可能提交。
5 : PROPAGATION_NOT_SUPPORTED
當(dāng)前不支持事務(wù)。比如 ServiceA.methodA 的事務(wù)級(jí)別是 PROPAGATION_REQUIRED ,而 ServiceB.methodB 的事務(wù)級(jí)別是 PROPAGATION_NOT_SUPPORTED ,
那么當(dāng)執(zhí)行到 ServiceB.methodB 時(shí), ServiceA.methodA 的事務(wù)掛起,而他以非事務(wù)的狀態(tài)運(yùn)行完,再繼續(xù) ServiceA.methodA 的事務(wù)。
6 : PROPAGATION_NEVER
不能在事務(wù)中運(yùn)行。假設(shè) ServiceA.methodA 的事務(wù)級(jí)別是 PROPAGATION_REQUIRED , 而 ServiceB.methodB 的事務(wù)級(jí)別是 PROPAGATION_NEVER ,
那么 ServiceB.methodB 就要拋出異常了。
7 : PROPAGATION_NESTED
理解 Nested 的關(guān)鍵是 savepoint 。他與 PROPAGATION_REQUIRES_NEW 的區(qū)別是, PROPAGATION_REQUIRES_NEW 另起一個(gè)事務(wù),將會(huì)與他的父事務(wù)相互獨(dú)立,
而 Nested 的事務(wù)和他的父事務(wù)是相依的,他的提交是要等和他的父事務(wù)一塊提交的。也就是說(shuō),如果父事務(wù)最后回滾,他也要回滾的。
而 Nested 事務(wù)的好處是他有一個(gè) savepoint 。
相關(guān)文章
centos7中如何利用crontab進(jìn)行mysql定時(shí)備份
crontab是一個(gè)命令,常見(jiàn)于Unix和類Unix的操作系統(tǒng)之中,用于設(shè)置周期性被執(zhí)行的指令,下面這篇文章主要給大家介紹了關(guān)于centos7中如何利用crontab進(jìn)行mysql定時(shí)備份的相關(guān)資料,需要的朋友可以參考下2022-02-02關(guān)于數(shù)據(jù)庫(kù)中的查詢優(yōu)化
這篇文章主要介紹了關(guān)于數(shù)據(jù)庫(kù)中的查詢優(yōu)化,對(duì)于大型的應(yīng)用系統(tǒng),數(shù)據(jù)動(dòng)輒上百萬(wàn),就需要了解DBMS對(duì)查詢語(yǔ)句的處理過(guò)程和優(yōu)化算法,更好的利用其優(yōu)化算法,以提高系統(tǒng)的性能,需要的朋友可以參考下2023-07-07mysql 查詢當(dāng)天、本周,本月,上一個(gè)月的數(shù)據(jù)
這篇文章主要介紹了mysql 查詢當(dāng)天、本周,本月,上一個(gè)月的數(shù)據(jù)的sql代碼,在文中還給大家提到了mysql如何查詢當(dāng)天信息,具體內(nèi)容詳情大家參考下本文2018-01-01一臺(tái)linux主機(jī)啟動(dòng)多個(gè)MySQL數(shù)據(jù)庫(kù)的方法
這篇文章主要介紹了一臺(tái)linux主機(jī)啟動(dòng)多個(gè)MySQL數(shù)據(jù)庫(kù)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03解析mysql數(shù)據(jù)庫(kù)還原錯(cuò)誤:(mysql Error Code: 1005 errno 121)
本篇文章是對(duì)mysql數(shù)據(jù)庫(kù)還原錯(cuò)誤:(mysql Error Code: 1005 errno 121)的解決方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06