廣州微信網(wǎng)站建設(shè)咨詢網(wǎng)站建設(shè)關(guān)鍵詞排名
日志
在數(shù)據(jù)庫中,如何保證數(shù)據(jù)的回滾,以及數(shù)據(jù)同步,系統(tǒng)宕機(jī)后可以恢復(fù)到原來的狀態(tài),其實(shí)就是依靠日志。
其中bin log是Server層特有的,redo log是Innodb存儲引擎特有的。
bin log 是邏輯日志,主要記錄這條SQL的原始邏輯,比如 name 設(shè)置為abc
redo log是物理日志,在某個(gè)數(shù)據(jù)頁上做了什么修改。
一個(gè)案例
假設(shè)我們現(xiàn)在要對t表,(id,name) update t set name=‘qxlx’ where id = 1;設(shè)置操作,
根據(jù)上一篇數(shù)據(jù)庫基礎(chǔ)架構(gòu)篇,這條SQL執(zhí)行的流程都會走連接器,查詢緩存,分析器,優(yōu)化器,最后到執(zhí)行器。
1.執(zhí)行器根據(jù)建表的存儲引擎來覺得使用哪個(gè)存儲引擎,一般都是InnoDB。因?yàn)镮nnoDB中存在change buffer這樣的機(jī)制,所以會先查詢change buffer中有沒有數(shù)據(jù),如果有的話,直接操作更新,沒有的話會先從磁盤中查詢數(shù)據(jù),返回給執(zhí)行器。之后寫入undo log 日志。
2.如何保證SQL沒有提交,可以回滾到之前的狀態(tài)呢,
在執(zhí)行如上的SQL的之后,會先寫入undo log,進(jìn)行標(biāo)記原始數(shù)據(jù)是什么 比如name = abc, 如果這個(gè)SQL沒有提交事務(wù),那么數(shù)據(jù)就會回滾到之前的狀態(tài) name=abc。
3.寫入bin log日志。其實(shí)這個(gè)流程比較復(fù)雜,我們來慢慢梳理以下,具體的執(zhí)行流程圖在如下。
a.先從存儲引擎中獲取id=1這樣數(shù)據(jù),如果在內(nèi)存中的話,那么直接返回,否則話,從磁盤中讀取到數(shù)據(jù)。將數(shù)據(jù)返回給執(zhí)行器
b.執(zhí)行器會進(jìn)行數(shù)據(jù)增加操作,name=‘qxlx’,寫入新的一行,將數(shù)據(jù)更新到內(nèi)存中,redo log此時(shí)處于prepare階段,Server層寫入bin log,存儲引擎將redo log提交。
WAL
在寫redo log日志的時(shí)候,一般來說,我們可以先把數(shù)據(jù)寫到臨時(shí)的緩存中,然后等到一定的時(shí)候比如mysql空閑的時(shí)候,在同步寫回到磁盤中。而這樣的話可以避免大量的IO 和 數(shù)據(jù)查找操作。這種機(jī)制就是 writer ahead logging技術(shù)。而redo log的區(qū)域是固定的,也就是寫滿的之后,需要強(qiáng)制刷新數(shù)據(jù)到磁盤中。
而如果要強(qiáng)制更新到磁盤中,可以通過以下參數(shù)強(qiáng)制更新到磁盤中。sync_binlog設(shè)置成1,也可以保證bin log 實(shí)時(shí)存儲到磁盤中,保證系統(tǒng)重啟后數(shù)據(jù)不會丟失。
innodb_flush_log_at_trx_commit = 1
sync_binlog = 1
其實(shí)可以想一下,一個(gè)學(xué)生正在聽課,老師講的比較快的時(shí)候,是趕不上講筆記全部整理到自己的筆記本上,可以先寫到抄本上,然后在下課后,講筆記整理到筆記本上。
兩階段提交
以上在寫入bin log和 redo log的時(shí)候,先寫redo log 然后bin log redolog提交,需要這么麻煩嘛,我們這里分析以下。如果將兩個(gè)過程分開來寫的話
1.先寫bin log,然后此時(shí)系統(tǒng)宕機(jī)了,重啟之后,因?yàn)閞edo log沒有寫入,bin log(name=‘qxlx’) ,如果需要按照bin log進(jìn)行數(shù)據(jù)同步到從庫上,那么數(shù)據(jù)就是錯(cuò)誤的,數(shù)據(jù)庫本上是(name=‘a(chǎn)bc’)
2.先寫redo log,然后系統(tǒng)宕機(jī),重啟之后,redo log (name=‘qxlx’) 但是數(shù)據(jù)庫 (name=‘a(chǎn)bc’) ,會按照redo log進(jìn)行重新更新數(shù)據(jù),此時(shí)數(shù)據(jù)被更新為 (name=‘qxlx’) 所以數(shù)據(jù)不一致了,所以需要按照兩階段提交的方式來執(zhí)行保證數(shù)據(jù)的一致性。
資料來源:mysql45講