Mysql-事務(wù)

事務(wù)特性ACID

原子性(Atomicity):事務(wù)作為一個(gè)整體被執(zhí)行,包含在其中的對數(shù)據(jù)庫的操作要么全部被執(zhí)行,要么都不執(zhí)行。

一致性(Consistency):事務(wù)應(yīng)確保數(shù)據(jù)庫的狀態(tài)從一個(gè)一致狀態(tài)轉(zhuǎn)變?yōu)榱硪粋€(gè)一致狀態(tài)。一致狀態(tài)的含義是數(shù)據(jù)庫中的數(shù)據(jù)應(yīng)滿足完整性約束。

隔離性(Isolation):多個(gè)事務(wù)并發(fā)執(zhí)行時(shí),一個(gè)事務(wù)的執(zhí)行不應(yīng)影響其他事務(wù)的執(zhí)行。

持久性(Durability):已被提交的事務(wù)對數(shù)據(jù)庫的修改應(yīng)該永久保存在數(shù)據(jù)庫中。

事務(wù)的原子性、一致性、持久性是通過redo/undo log來實(shí)現(xiàn)的

事務(wù)的隔離性是通過鎖來實(shí)現(xiàn)的

事務(wù)理解

持久性理解

首先來看一下事務(wù)的持久性,也許你會(huì)問,事務(wù)的持久性:難道不應(yīng)該等待數(shù)據(jù)最終寫到數(shù)據(jù)文件中完成持久化嗎?

是的,確實(shí)是這樣,而且如果等數(shù)據(jù)最終寫到數(shù)據(jù)文件中標(biāo)志事務(wù)結(jié)束,這樣絕對確保了事務(wù)的持久性,而且根本不需要什么redo log!

按照上述理解,梳理一下事務(wù)的基本流程:

1,事務(wù)開啟

2,先從磁盤中將需要變更的數(shù)據(jù)讀入至內(nèi)存

3,在內(nèi)存中將數(shù)據(jù)更新

4,寫binlog,并刷到磁盤中

5,將內(nèi)存中更改后的數(shù)據(jù)刷至數(shù)據(jù)文件

6,事務(wù)提交成功

這種流程的瓶頸在于第5步,由于數(shù)據(jù)寫到數(shù)據(jù)文件是IO隨機(jī)寫,速度是非常慢的,所有事務(wù)的提交將阻塞在這個(gè)過程??梢岳斫饧僭O(shè)update.. where id=1, update.. where id=999,這樣兩條數(shù)據(jù)之前是分布在不同的磁盤區(qū)域中,現(xiàn)在需要先進(jìn)行查找再寫入,這是非常慢的。

于是innodb做了一系列優(yōu)化,在第5步,這里不是等數(shù)據(jù)寫回至數(shù)據(jù)文件,而是用寫redo log來替代。redo log是一種物理日志,類似于內(nèi)存快照,以追加的方式記錄,是順序IO,寫入速度是非常快的。

所以,真正的事務(wù)并不會(huì)等到數(shù)據(jù)真正寫入數(shù)據(jù)中才返回,引入真正的事務(wù)提交過程:

事務(wù)提交

insert into values( ...);

1、從數(shù)據(jù)庫將需修改數(shù)據(jù)讀入內(nèi)存中Buffer Pool(下圖中無需讀入數(shù)據(jù),已忽略)

2、在內(nèi)存中寫undolog

3、在內(nèi)存中更新數(shù)據(jù),產(chǎn)生臟頁Dirty Page(此時(shí)與數(shù)據(jù)文件中的內(nèi)容不一致)

4、將事務(wù)過程中的變更寫入redo log

5、事務(wù)提交,寫bin log

6、redo log 第二階段,如果5寫入成功則commit(即寫入提交成功的標(biāo)志),否則rollback

后臺線程刷磁盤操作(undolog和數(shù)據(jù)文件的刷入):

1、將undolog 寫入磁盤

2、將數(shù)據(jù)寫入磁盤

我們知道undo log用于事務(wù)的回滾的,理論上跟redo log一樣,也必須在事務(wù)提交之前寫入磁盤的,而且必須在redo log之前寫入!但是仔細(xì)看下面淘寶丁奇大神的圖,會(huì)發(fā)現(xiàn)undo log的寫入并不需要在事務(wù)提交之前完成。這是為何?實(shí)際上Undo和Redo Log的這種關(guān)聯(lián),使得持久化變得復(fù)雜起來。

于是innodb又又作了寫優(yōu)化:將Undo Log看作數(shù)據(jù),因此記錄Undo Log的操作也會(huì)記錄到redo log中。這樣undo log就可以象數(shù)據(jù)一樣緩存起來,而不用在redo log之前寫入磁盤了。

包含Undo Log操作的Redo Log,看起來是這樣的:

記錄1: trx1, Undo log insert undo_insert …

記錄2: trx1, insert …

記錄3: trx2, Undo log insert undo_update …

記錄4: trx2, update …

記錄5: trx3, Undo log insert undo_delete …

記錄6: trx3, delete …

所以,undolog 由后臺線程寫入,不用在redo log之前寫盤了,不過還是必須在數(shù)據(jù)寫入磁盤之前寫入。


事務(wù)與日志

binlog

文件:mysql-bin.000001,mysql-bin.000002..

目的:mysql server層的日志,屬于邏輯日志,記錄的是變更的sql語句,用于數(shù)據(jù)庫宕機(jī)恢復(fù),主備復(fù)制等

log_bin=/var/lib/mysql/binlog/mysql-bin

redo log

文件:ib_logfile*文件,

目的:持久性,參照事務(wù)提交過程

innodb_log_group_home_dir=./logs/redolog(./是mysqlld根目錄)

undo log

文件:默認(rèn)存放在共享表空間內(nèi),ibdata*文件,磁盤上不存在單獨(dú)的undo log文件,

? ? ? 5.6以后也可以設(shè)置為獨(dú)立的文件:innodb_undo_tablespaces

目的:比較好理解,保存的是變更發(fā)生之前的數(shù)據(jù),用于回滾


參考:

http://9i9icenter.com/huanqiuNews/599f30ca2277046518e85878

http://www.ywnds.com/?p=8282

https://www.slideshare.net/mryufeng/mysqlio-12891332

http://www.zhdba.com/mysqlops/2012/04/06/innodb-log1/

http://www.cnblogs.com/xinysu/p/6555082.html

http://www.zhdba.com/mysqlops/2012/04/06/innodb-log1/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容