大家好,我是安小生,繼續(xù)數(shù)據(jù)庫(kù)的總結(jié):MySQL的事物,
那么什么是事物呢?
事務(wù)是MySQL區(qū)別于NoSQL的重要特征,是保證關(guān)系型數(shù)據(jù)庫(kù)數(shù)據(jù)一致性的關(guān)鍵技術(shù)。事務(wù)可看作是對(duì)數(shù) 據(jù)庫(kù)操作的基本執(zhí)行單元,可能包含一個(gè)或者多個(gè)SQL語(yǔ)句。這些語(yǔ)句在執(zhí)行時(shí),要么都執(zhí)行,要么都不執(zhí) 行。
事物的應(yīng)用場(chǎng)景有那些呢?
- 事物的場(chǎng)景使用:金額交易,跨表操作。銀行,秒殺都會(huì)用到事物操作。
- 事物的四大特性:
原子性:要么全部執(zhí)行,要么全部執(zhí)行失敗。
一致性:要求數(shù)據(jù)由一個(gè)狀態(tài)轉(zhuǎn)化為另一個(gè)狀態(tài)。
持久性:保證數(shù)據(jù)不會(huì)丟失,
隔離性:事物與事物之間不會(huì)互相影響。
事物的基本語(yǔ)法
- 在 MySQL 命令行的默認(rèn)設(shè)置下,事務(wù)是自動(dòng)提交的,即執(zhí)行了SQL 語(yǔ)句之后會(huì)馬上執(zhí)行 commit 操 作,我們可以設(shè)置 set autocommit=0 來(lái)禁用當(dāng)前回話的自動(dòng)提交。
- 還可以用 begin 、start transaction 來(lái)顯式的開(kāi)始一個(gè)事務(wù)。
- commit 在默認(rèn)設(shè)置下是等價(jià)于 commit work 的,表示提交事務(wù)。
- rollback 在默認(rèn)設(shè)置下等價(jià)于 rollback work,表示事務(wù)回滾。
- savepoint xxx 表示定義一個(gè)保存點(diǎn),在一個(gè)事務(wù)中可以有多個(gè)保存點(diǎn)。
- release savepoint xxx 表示刪除一個(gè)保存點(diǎn),當(dāng)沒(méi)有該保存點(diǎn)的時(shí)候執(zhí)行該語(yǔ)句,會(huì)拋出一個(gè)異常。
- rollback to [savepoint] xxx 表示回滾到某個(gè)保存點(diǎn)。
查詢事物提交語(yǔ)句
show variables like '%commit%';
事物的隔離級(jí)別
- 讀取未提交:另一個(gè)事物修改了數(shù)據(jù),但尚未提交,而本事物中的select會(huì)讀到未被提交的數(shù)據(jù),也是臟讀。
- 讀取已提交:一個(gè)A事物多次讀取已經(jīng)提交的數(shù)據(jù),而B(niǎo)事物在讀取的時(shí)候已經(jīng)把改數(shù)據(jù)修改了,然后導(dǎo)致2個(gè)事物讀取的數(shù)據(jù)不一樣。
- 可重讀取(默認(rèn)是RR):事物在開(kāi)啟的時(shí)候,select的結(jié)果是事物開(kāi)始時(shí)間點(diǎn)的狀態(tài),因?yàn)閟elect讀取的數(shù)據(jù)會(huì)是一致的,但是會(huì)出現(xiàn)幻讀。
- 串行化:最高的隔離級(jí)別,在這個(gè)隔離級(jí)別下,不產(chǎn)生任何異常,并發(fā)事物,就像事物是一個(gè)個(gè)按照順序執(zhí)行一樣。
事物的生命周期
1 原子性的實(shí)現(xiàn)
begin;
select * from user where id =1;.
commit;
rollback
事務(wù)日志文件 =》 重做日志 redo log =>ib_logfile0 重新執(zhí)行
回滾日志 undo log =>ibdata 回滾數(shù)據(jù)
mysql對(duì)于事務(wù)的執(zhí)行 => 日志先行凡是sql執(zhí)行都會(huì)執(zhí)行事務(wù)
日志優(yōu)先級(jí)大于實(shí)際操作的數(shù)據(jù)的 所有執(zhí)行的sql都會(huì)先執(zhí)行日志,在寫(xiě)數(shù)據(jù)
事務(wù)重做日志與回滾日志
-- 查看事務(wù)日志 :
show engine innodb status\G;
-- 查看日志文件設(shè)置狀態(tài)
show variables like 'innodb_%';
innodb_log_files_in_group:DB中設(shè)置幾組事務(wù)日志,默認(rèn)是2; innodb_log_group_home_dir:事務(wù)日志存放 目錄,不設(shè)置,ib_logfile0...存在在數(shù)據(jù)文件目錄下 Innodb存儲(chǔ)引擎可將所有數(shù)據(jù)存放于ibdata*的共享表空 間,也可將每張表存放于獨(dú)立的.ibd文件的獨(dú)立表空間
注意:在MySQL中對(duì)于數(shù)據(jù)來(lái)說(shuō), 最為重要的是日志文件
redo log => ib_logfile0
undo log => ibdata
-
重做日志
- 持久化:事物被提交了,數(shù)據(jù)一定被寫(xiě)入到數(shù)據(jù)中了,并且被保存了,這樣事物已經(jīng)被提交了,就無(wú)法再次回滾了。
- 重做日志持久化:與原子性一樣,事務(wù)的持久性也是通過(guò)日志來(lái)實(shí)現(xiàn)的,MySQL 使用重做日志(redo log)實(shí)現(xiàn)事務(wù)的持久 性,重做日志由兩部分組成,一是內(nèi)存中的重做日志緩沖區(qū),因?yàn)橹刈鋈罩揪彌_區(qū)在內(nèi)存中,所以它是易 失的,另一個(gè)就是在磁盤(pán)上的重做日志文件,它是持久的。
知識(shí)點(diǎn)
在mysql中事務(wù)執(zhí)行commit提交了之后,但是服務(wù)器掛了,數(shù)據(jù)還沒(méi)有寫(xiě)入磁盤(pán),在mysql重啟服務(wù)之后會(huì) 重新執(zhí)行這個(gè)重做日志寫(xiě)入數(shù)據(jù)。
-
回滾日志
- 原子性:專業(yè)點(diǎn):事務(wù)就是一系列的操作,要么全部都執(zhí)行,要都不執(zhí)行。
- 回滾原子性日志:想要保證事務(wù)的原子性,就需要在異常發(fā)生時(shí),對(duì)已經(jīng)執(zhí)行的操作進(jìn)行回滾,而在 MySQL 中,恢復(fù)機(jī)制是通過(guò)回滾日志(undo log)實(shí)現(xiàn)的,所有事務(wù)進(jìn)行的 修改都會(huì)先記錄到這個(gè)回滾日志中,然后在對(duì)數(shù)據(jù)庫(kù) 中的對(duì)應(yīng)行進(jìn)行寫(xiě)入。
知識(shí)點(diǎn):
系統(tǒng)發(fā)生崩潰、數(shù)據(jù)庫(kù)進(jìn)程直接被殺死后,當(dāng)用戶再次啟動(dòng)數(shù)據(jù)庫(kù)進(jìn)程時(shí), 還能夠立刻通過(guò)查詢回滾日志將之前未完成的事務(wù)進(jìn)行回滾,這也就需要回滾 日志必須先于數(shù)據(jù)持久化到 磁盤(pán)上,是我們需要先寫(xiě)日志后寫(xiě)數(shù)據(jù)庫(kù)的主要原因。
重做日志與回滾日志
到現(xiàn)在為止我們了解了 MySQL 中的兩種日志,回滾日志(undo log)和重做日志(redo log);在數(shù)據(jù)庫(kù) 系統(tǒng)中,事務(wù)的原子性和持久性是由事務(wù)日志 (transaction log)保證的,在實(shí)現(xiàn)時(shí)也就是上面提到的兩種 日志,前者用于對(duì)事務(wù)的影響進(jìn)行撤銷,后者在錯(cuò)誤處理時(shí)對(duì)已經(jīng)提交的事務(wù)進(jìn)行重做,它們能保 證兩 點(diǎn):
- 發(fā)生錯(cuò)誤或者需要回滾的事務(wù)能夠成功回滾(原子性);
- 在事務(wù)提交后,數(shù)據(jù)沒(méi)來(lái)得及寫(xiě)會(huì)磁盤(pán)就宕機(jī)時(shí),在下次重新啟動(dòng)后能夠成功恢復(fù)數(shù)據(jù)(持久性);在數(shù)據(jù)庫(kù)中,這兩種日志經(jīng)常都是一起工作的,我們可以將它們整體看做一條事務(wù)日志,其中包含了 事務(wù)的 ID、修改的行元素以及修改前后的值。