柚子快報(bào)邀請碼778899分享:MySQL —— 事務(wù)
柚子快報(bào)邀請碼778899分享:MySQL —— 事務(wù)
概念
事務(wù)把?組SQL語句打包成為?個(gè)整體,在這組SQL的執(zhí)行過程中,要么全部成功,要么全部失敗。 這組SQL語句可以是?條也可以是多條。
ACID 特性
原子性
Atomicity(原子性):一個(gè)事務(wù)中的所有操作,要么全部成功,要么全部失敗,不會(huì)出現(xiàn)只執(zhí)行了一半的情況。如果事務(wù)在執(zhí)行過程中發(fā)生錯(cuò)誤,會(huì)回滾(Rollback )到事務(wù)開始前的狀態(tài),就像這個(gè)事務(wù)從來沒有執(zhí)行過一樣。
一致性
Consistency (一致性):在事務(wù)開始之前和事務(wù)結(jié)束以后,數(shù)據(jù)庫的完整性不會(huì)被破壞。這表示寫入的數(shù)據(jù)必須完全符合所有的預(yù)設(shè)規(guī)則,包括數(shù)據(jù)的精度、關(guān)聯(lián)性以及關(guān)于事務(wù)執(zhí)行過程中服務(wù)器崩潰后如何恢復(fù)。
以轉(zhuǎn)賬為例:兩個(gè)人之間相互轉(zhuǎn)賬,必須保證兩個(gè)人的總金額是不變的,這就是一致性。
隔離性
Isolation (隔離性):**數(shù)據(jù)庫允許多個(gè)并發(fā)事務(wù)同時(shí)對數(shù)據(jù)進(jìn)行讀寫和修改,隔離性可以防止多個(gè)事務(wù)并發(fā)執(zhí)行時(shí)由于交叉執(zhí)行而導(dǎo)致數(shù)據(jù)的不一致。**事務(wù)可以指定不同的隔離級別,以權(quán)衡在不同的應(yīng)用場景下數(shù)據(jù)庫性能和安全。
以轉(zhuǎn)賬為例:張三進(jìn)行購物,同時(shí)李四也進(jìn)行購物,兩人用于支付的銀行卡(假設(shè)有一千元)是一樣,假設(shè)兩個(gè)人同時(shí)輸入密碼,同時(shí)發(fā)起轉(zhuǎn)賬申請,這時(shí)候銀行那邊就是接收到兩個(gè)同時(shí)發(fā)生的事務(wù),為了轉(zhuǎn)賬成功,兩個(gè)事務(wù)的執(zhí)行需要進(jìn)行隔離,就是張三進(jìn)行扣款100元之后,余額變?yōu)?00,之后執(zhí)行李四的扣款100元,余額變?yōu)?00,這就是隔離性。 如果沒有進(jìn)行隔離,就是同時(shí)扣款100,最后余額會(huì)變成900。
持久性
Durability (持久性):事務(wù)處理結(jié)束后,對數(shù)據(jù)的修改將永久的寫入存儲(chǔ)介質(zhì),即便系統(tǒng)故障也不會(huì)丟失。
還是以轉(zhuǎn)賬為例:轉(zhuǎn)賬完成后,兩個(gè)人的最后的金額要永久保存起來。
事務(wù)的使用
事務(wù)具備的ACID特性,是我們使用事務(wù)的原因,在我們?nèi)粘5臉I(yè)務(wù)場景中有大量的需求要用事務(wù)來保證。支持事務(wù)的數(shù)據(jù)庫能夠簡化我們的編程模型,不需要我們?nèi)タ紤]各種各樣的潛在錯(cuò)誤和并發(fā)問題,在使用事務(wù)過程中,要么提交,要么回滾,不用去考慮網(wǎng)絡(luò)異常,服務(wù)器宕機(jī)等其他因素,因此我們經(jīng)常接觸的事務(wù)本質(zhì)上是數(shù)據(jù)庫對 ACID 模型的?個(gè)實(shí)現(xiàn),是為應(yīng)層用服務(wù)的。
要使用事務(wù)那么數(shù)據(jù)庫就要支持事務(wù),在MySQL中支持事務(wù)的存儲(chǔ)引擎是InnoDB,可以通過show engines; 語句查看:
事務(wù)的語法:
# 開始一個(gè)新事務(wù)
start transaction;
# 或者
begin;
# 提交當(dāng)前事務(wù),并對更改持久化保存
commit;
# 回滾當(dāng)前事務(wù),取消其更改
rollback;
演示: 首先開啟事務(wù),并查看當(dāng)前的學(xué)生表
把最后一行的白糖修改為趙六:
我們進(jìn)行事務(wù)的回滾,事務(wù)沒有進(jìn)行提交,就不會(huì)進(jìn)行數(shù)據(jù)的修改。
我們演示一下事務(wù)的提交: 開啟事務(wù),進(jìn)行更新操作(將錢七這個(gè)名字改成王五),進(jìn)行事務(wù)提交。
保存點(diǎn)
在事務(wù)執(zhí)行的過程中設(shè)置保存點(diǎn),回滾時(shí)指定保存點(diǎn)可以把數(shù)據(jù)恢復(fù)到保存點(diǎn)的狀態(tài)
語法:
# 設(shè)置保存點(diǎn)
savepoint point_name;
# 回滾到指定保存點(diǎn)
rollback to point_name;
演示: 開啟事務(wù): 把王五這條記錄刪除,并且保存這個(gè)保存點(diǎn)
再次進(jìn)行更新操作:
這時(shí)候突然發(fā)現(xiàn),更新操作失誤了,更新錯(cuò)人了,我們可以回滾到保存點(diǎn)1:
自動(dòng) / 手動(dòng)提交事務(wù)
默認(rèn)情況下,MySQL是自動(dòng)提交事務(wù)的,也就是說我們執(zhí)行的每個(gè)CRUD操作,,都會(huì)自動(dòng)開啟?個(gè)事務(wù)并在語句執(zhí)行完成之后自動(dòng)提交,發(fā)生異常時(shí)自動(dòng)回滾。
我們來查看MySQL 事務(wù)提交是自動(dòng)的還是手動(dòng)的:
ON 表示是自動(dòng)提交事務(wù)。
設(shè)置語法:
# 設(shè)置事務(wù)自動(dòng)提交
set autocommit = 1; # 方式一
set autocommit = on; # 方式二
# 設(shè)置事務(wù)手動(dòng)提交
set autocommi = 0; # 方式一
set autocommit = off; # 方式二
注意: 只要使用 START TRANSACTION 或 BEGIN 開啟事務(wù),必須要通過 COMMIT 提交才會(huì)持久化,與是否設(shè)置 SET autocommit 無關(guān)。
手動(dòng)提交模式下,不用顯示開啟事務(wù),執(zhí)行修改操作后,提交或回滾事務(wù)時(shí)直接使用 commit 或 rollback
已提交的事務(wù)不能回滾
隔離級別
MySQL服務(wù)可以同時(shí)被多個(gè)客戶端訪問,每個(gè)客戶端執(zhí)行的DML語句以事務(wù)為基本單位,那么不同的客戶端在對同?張表中的同?條數(shù)據(jù)進(jìn)行修改的時(shí)候就可能出現(xiàn)相互影響的情況,為了保證不同的事務(wù)之間在執(zhí)行的過程中不受影響,那么事務(wù)之間就需要要相互隔離,這種特性就是隔離性。
事務(wù)間不同程度的隔離,稱為事務(wù)的隔離級別;不同的隔離級別在性能和安全方面做了取舍,有的隔離級別注重并發(fā)性,優(yōu)點(diǎn)注重安全性,有的則是并發(fā)和安全始終,在MySQL的InnoDB 引擎中事務(wù)的隔離級別有四種: read uncommitted 讀未提交 read committed 讀已提交 repeatable read 可重復(fù)讀 (默認(rèn)) serializable 串行化
查看隔離級別
事務(wù)的隔離級別分為全局作用域和會(huì)話作用域,查看不同作用域事務(wù)的隔離級別,可以使用以下的方式:
# 全局作用域
select @@global.transaction_isolation;
# 當(dāng)前會(huì)話作用域
select @@session.transaction_isolation;
MySQL默認(rèn)隔離級別為可重復(fù)讀
設(shè)置隔離級別 以及 不同隔離級別存在的問題
語法:
# 通過GLOBAL|SESSION分別指定不同作?域的事務(wù)隔離級別
SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL level|access_mode;
# 隔離級別
level: {
REPEATABLE READ # 可重復(fù)讀
| READ COMMITTED # 讀已提交
| READ UNCOMMITTED # 讀未提交
| SERIALIZABLE # 串?化
}
# 訪問模式
access_mode: {
READ WRITE # 表?事務(wù)可以對數(shù)據(jù)進(jìn)?讀寫
| READ ONLY # 表?事務(wù)是只讀,不能對數(shù)據(jù)進(jìn)?讀寫
}
# ?例
# 設(shè)置全局事務(wù)隔離級別為串?化,后續(xù)所有事務(wù)?效,不影響當(dāng)前事務(wù)
SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;
# 設(shè)置會(huì)話事務(wù)隔離級別為串?化,當(dāng)前會(huì)話后續(xù)的所有事務(wù)?效,不影響當(dāng)前事務(wù),可以在任何時(shí)候執(zhí)?
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
# 如果不指定任何作?域,設(shè)置只針對下?個(gè)事務(wù),隨后的事務(wù)恢復(fù)之前的隔離級別
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
下面演示不同的隔離級別,會(huì)開啟兩個(gè)MySQL會(huì)話窗口。
讀未提交
先設(shè)置隔離級別:
開啟兩個(gè)事務(wù): 查看我們的課程表: 當(dāng)我們開啟事務(wù)進(jìn)行修改操作的時(shí)候,發(fā)現(xiàn)事務(wù)還沒有提交,就已經(jīng)被人看到了事務(wù)未提交的內(nèi)容,這種就叫做臟讀
臟讀就是讀取到別人未提交的事務(wù)內(nèi)容。
讀已提交
設(shè)置隔離級別:
查看課程表:
開啟兩個(gè)事務(wù):
現(xiàn)在我們進(jìn)行修改操作,當(dāng)沒有提交的時(shí)候,其他會(huì)話讀取的時(shí)候是讀不到未提交的內(nèi)容。
當(dāng)我們提交事務(wù)之后,其他會(huì)話才能讀到 ENGLISH 這條數(shù)據(jù)。
這時(shí)候有一個(gè)問題,就是一個(gè)會(huì)話已知進(jìn)行修改與提交事務(wù),另一個(gè)會(huì)話進(jìn)行讀取數(shù)據(jù)的時(shí)候就會(huì)發(fā)現(xiàn)數(shù)據(jù)會(huì)一直變化,可是另一個(gè)會(huì)話并不想接收到修改的數(shù)據(jù)ENGLISH,只是想查看之前的數(shù)據(jù)(英文)的時(shí)候,就會(huì)特別煩惱。
這種問題我們稱為不可重復(fù)讀,不可重復(fù)讀指,讀取到了修改的數(shù)據(jù)。
可重復(fù)讀
設(shè)置隔離級別:
查看課程表:
首先開啟兩個(gè)事務(wù):
其中一個(gè)事務(wù)將ENGLISH 修改未英文并提交事務(wù),
另一個(gè)事務(wù)沒有受到上面事務(wù)的影響,還是讀取到的是ENGLISH
但是可重復(fù)讀有一個(gè)問題:就是如果事務(wù)進(jìn)行插入、刪除操作的時(shí)候,影響的是結(jié)果集,在另一個(gè)事務(wù)在查詢的時(shí)候,結(jié)果集也會(huì)隨之發(fā)生改變。這種情況就叫做幻讀。
演示一下: 首先開始兩個(gè)事務(wù),一個(gè)事務(wù)對課程表進(jìn)行插入操作并且進(jìn)行提交。
這時(shí)候另一個(gè)事務(wù)會(huì)話查看的時(shí)候發(fā)現(xiàn)多了一個(gè)結(jié)果,這就是幻讀。
刪除也是:
串行化
串行化就是最高程度的隔離級別。兩個(gè)事務(wù)都互不影響。
一個(gè)事務(wù)進(jìn)行CRUD 操作的時(shí)候,不會(huì)影響到其他事務(wù)對同一個(gè)表的查詢,也就是串行化不存在臟讀,不可重復(fù)讀、幻讀的隔離問題。
小結(jié)
隔離級別臟讀不可重復(fù)讀幻讀read uncommitted存在存在存在read committed不存在存在存在repeatable read不存在不存在存在serializable不存在不存在不存在
從上到下并發(fā)性依次降低,隔離性依次提高。
柚子快報(bào)邀請碼778899分享:MySQL —— 事務(wù)
好文閱讀
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。