由內部分佈式事務保證mysql
咱們先來了解下,當一個commit敲下後,內部會發生什麼?sql
步驟 | 操做 |
---|---|
step1 | InnoDB作prepare redo log(fsync) |
step2 | Sever層寫binlog(fsync) |
step3 | InnoDB層commit redo log(fsync) |
第一步寫的redo file,寫入的是trxid而不是page的變化(show binlog events in 'xxx'),準確的說寫在undo頁上數據庫
第三步寫的也是redo file緩存
以上說的寫入指的的成功落盤多線程
這裏的原理是一個內部的分佈式事務,相關參數:innodb_support_xa=onmvc
tips:oracle
5.6默認開啓分佈式事務(binlog和redo log同步),5.7你設置off也沒用,保證強一致性分佈式
服務crash,一個事務可能面對的狀態以下:性能
tips:測試
①不談高可用的狀況下,若是兩個日誌都寫成功,其實commit和rollback都沒有問題,用戶並不知道他commit會不會成功,他只知道數據庫斷了,這種事務叫partial transaction,可提交可不提交
②mysql這裏作commit是爲了複製數據同步
③寫重作日誌oracle一次fsync,mysql要三次?
第一步或者第二步失敗,天然沒有第三次,前兩步成功的話,其實第三步不用寫到磁盤持久化,只要寫到操做系統緩存就能夠,不論是否有沒有commit的日誌,都會提交,因此實際上是兩次,可是有組提交加持,可能2次fsync提交了10個事務都有可能
在innodb層,prepare redo log中會記錄一個trxid,宕機從新起來恢復時
step1
先scan binlog,把全部的trxid拿出來作一個hash table(掃最後一個binlog文件,一個事務的日誌是不能跨文件的)
step2
去scan innodb redo log,掃cp開始日後的部分,也會產生trxid list
step3
這時候去上面那個hash table中search,若是這個trxid在上面的hash表中,就是兩個步驟都沒問題,就commit,若是不在裏面(第二步寫binlog沒成功)就rollback
tips:
上面說的已是在數據庫層面了,也就是說用戶commit以後數據庫裏面作的東西,用戶是不能夠rollback的,也就是說應用層表現爲失敗,並不表明是真正的失敗
以上討論是crash臨界點地方處理
先回顧一下lsn
LSN log sequenct number 重作日誌寫入的字節量 LSN存在於: page redo log block checkpoint
看圖說恢復
背景:commit的本質就是每次提交後執行下面的操做
由innodb_flush_log_at_trx_commit參數決定
hdd盤的iops是100,那一秒鐘只能執行100次fsync,增刪改的qps的最大就是100(每作一個增刪改就提交一次) 因此咱們常常批量導入數據 批量導數據,begin;插10條;commit 這樣就只fsync了一次,這樣qps就提高了10倍
就這樣組提交誕生來了——一次fsync刷新一組事務(多線程)
性能提升10~100+倍,innodb存儲引擎原生支持,事務響應不會變慢的,不用擔憂
看兩個相關參數(5.7纔有)
binlog_group_commit_sync_delay 組提交必定要等待多少微秒,時間越長一次性提交的事務越多,fsync次數越少,性能越好 binlog_group_commit_sync_no_delay_count 累積到多少個才組提交
千萬不要調,你是調很差的呢,好比你調成5個事務,那你業務沒五個線程,那你就被hang住了,數據庫自身已經作的很好了
5.5有個bug,開啓binlog,組提交就會失效,設置雙1的話,性能會不好,那時候爲了緩解這個問題把innodb_flush_log_at_trx_commit設置爲2,crash可能最後一段事務丟失
tips:
另一個提高性能的參數
sync_binlog參數 5.7默認爲1,以前默認爲0
0表示事務提交後,binlog寫到操做系統緩存,操做系統控制怎麼寫到文件 1表示事務提交時binlog寫到磁盤 100表示100次事務提交刷一次磁盤
5.5中設置爲0是有提高,5.6以後就不會有這個問題了,並且0可能會有丟數據的風險
到這裏傳說中的innodb事務系統中的雙1到這裏就解釋清楚了,到如今爲止咱們就不用把這兩個值設爲其餘值了
附:官網的一句話:分佈式事務就要用serializable,這時候串行纔有意義,想不通
binlog 直接按事務提交順序
redo log 按帶星號的順序提交,只要page發生修改就會記錄到日誌中,因此T2修改的日誌能夠和T1是對同一個page修改
雖然都是T1 T2 T3,可是binlog記錄的是數據庫的操做,相似sql語句的
redo log記錄的是對page的修改,一個事務能夠對多個page進行修改,事務是並行在運行的,因此能夠有多個事務對多個不一樣的page在修改,因此提交順序比較特殊
redo log裏面一個事務的日誌能夠有不少,但binlog只有一個
redo log在事務提交過程當中就開始寫,binlog在事務提交最後纔開始寫
千萬記住redo log裏面沒記錄sql的
協助理解:
一個update操做,提交後寫了一個binlog,可是可能update修改了不少page進而產生了不少redo log,而後根據事務提交順序來寫盤,好比T1事務先操做了page A沒提交,T2事務跟着對page A作了修改提交了,這時候就會寫redo,此時T1事務還沒提交呢
tips: