MySQL 數(shù)據(jù)庫忽然斷電會丟數(shù)據(jù)嗎<轉載>
在上一章苞俘,我講解了 MySQL 鎖的相關內(nèi)容终抽。主要談到了全局鎖次乓、表鎖棚辽、行鎖以及死鎖等。通過這些學習劣针,相信我們可以理解鎖的原理拿撩,并在工作中降低鎖沖突的概率怔软。這也是優(yōu)化數(shù)據(jù)庫必須掌握的知識點垦细。
從本節(jié)開始,將進入一個新的 MySQL 知識大類:MySQL 事務挡逼。
什么是事務括改?
根據(jù)《高性能 MySQL》第 3 版 1.3 事務一節(jié)中定義:
事務就是一組原子性的 SQL 查詢,或者說一個獨立的工作單元家坎。如果數(shù)據(jù)庫引擎能夠成功地對數(shù)據(jù)庫應用該組查詢的全部語句嘱能,那么就執(zhí)行該組查詢。如果其中有任何一條語句因為崩潰或其他原因無法執(zhí)行乘盖,那么所有的語句都不會執(zhí)行。也就是說憔涉,事務內(nèi)的語句订框,要么全部執(zhí)行成功,要么全部執(zhí)行失敗兜叨。
看上面的文字可以稍微抽象了一點穿扳,可以結合生活中的一個例子:
比如你給朋友轉賬 100 元衩侥,其大致過程是:從你的賬戶扣除 100 元,然后再到你朋友的賬戶中增加 100 元矛物,試想茫死,如果在這中間,因為網(wǎng)絡問題或者程序問題履羞,導致在你的賬戶中扣除了峦萎,但是沒有在你朋友的賬戶中增加,那豈不是亂套了忆首。
所以爱榔,類似這種情況,就可以把這兩個步驟放到一個事務里面糙及。要么全部成功详幽,也就是從你的賬戶扣除之后,然后在你朋友賬戶中新增浸锨;要么全部失敗唇聘,比如在中間出現(xiàn)問題,會回滾這中間所有的變更柱搜。大致操作步驟如下表:
一個良好的事務處理系統(tǒng)迟郎,必須具備 ACID 特性:
atomicity(原子性) :要么全執(zhí)行,要么全都不執(zhí)行冯凹;consistency(一致性):在事務開始和完成時谎亩,數(shù)據(jù)都必須保持一致狀態(tài);isolation(隔離性) :事務處理過程中的中間狀態(tài)對外部是不可見的宇姚;durability(持久性) :事務完成之后匈庭,它對于數(shù)據(jù)的修改是永久性的。InnoDB 采用 redo log 機制來保證事務更新的一致性和持久性浑劳。什么是 redo log阱持?下面來一起看下:
2 Redo log
Redo log 稱為重做日志,用于記錄事務操作變化魔熏,記錄的是數(shù)據(jù)被修改之后的值衷咽。
Redo log 由兩部分組成:
內(nèi)存中的重做日志緩沖(redo log buffer)重做日志文件(redo log file)
每次數(shù)據(jù)更新會先更新 redo log buffer,然后根據(jù) innodb_flush_log_at_trx_commit 來控制 redo log buffer 更新到 redo log file 的時機蒜绽。innodb_flush_log_at_trx_commit 有三個值可選:
0:事務提交時镶骗,在事務提交時,每秒觸發(fā)一次 redo log buffer 寫磁盤操作躲雅,并調(diào)用操作系統(tǒng) fsync 刷新 IO 緩存鼎姊。
1:事務提交時,InnoDB 立即將緩存中的 redo 日志寫到日志文件中,并調(diào)用操作系統(tǒng) fsync 刷新 IO 緩存相寇;
2:事務提交時慰于,InnoDB 立即將緩存中的 redo 日志寫到日志文件中,但不是馬上調(diào)用 fsync 刷新 IO 緩存唤衫,而是每秒只做一次磁盤 IO 緩存刷新操作婆赠。
innodb_flush_log_at_trx_commit 參數(shù)的默認值是 1,也就是每個事務提交的時候都會從 log buffer 寫更新記錄到日志文件佳励,而且會刷新磁盤緩存休里,這完全滿足事務持久化的要求,是最安全的植兰,但是這樣會有比較大的性能損失份帐。
將參數(shù)設置為 0 時,如果數(shù)據(jù)庫崩潰楣导,最后 1秒鐘的 redo log 可能會由于未及時寫入磁盤文件而丟失废境,這種方式盡管效率最高,但是最不安全筒繁。
將參數(shù)設置為 2 時噩凹,如果數(shù)據(jù)庫崩潰,由于已經(jīng)執(zhí)行了重做日志寫入磁盤的操作毡咏,只是沒有做磁盤 IO 刷新操作驮宴,因此,只要不發(fā)生操作系統(tǒng)崩潰呕缭,數(shù)據(jù)就不會丟失堵泽,這種方式是對性能和安全的一種折中處理。
3 Binlog
二進制日志(binlog)記錄了所有的 DDL(數(shù)據(jù)定義語句)和 DML(數(shù)據(jù)操縱語句)恢总,但是不包括 select 和 show 這類操作迎罗。Binlog 有以下幾個作用:
恢復:數(shù)據(jù)恢復時可以使用二進制日志。復制:通過傳輸二進制日志到從庫片仿,然后進行恢復纹安,以實現(xiàn)主從同步。審計:可以通過二進制日志進行審計數(shù)據(jù)的變更操作砂豌。
可以通過參數(shù) sync_binlog 來控制累積多少個事務后才將二進制日志 fsync 到磁盤厢岂。
sync_binlog=0,表示每次提交事務都只write阳距,不fsync塔粒。sync_binlog=1,表示每次提交事務都會執(zhí)行fsync筐摘。sync_binlog=N(N>1)卒茬,表示每次提交事務都write映跟,累積N個事務后才fsync。比如要加快寫入數(shù)據(jù)的速度或者機器磁盤 IO 瓶頸時扬虚,可以將 sync_binlog 設置成大于 1 的值,但是如果設置為 N(N>1)時球恤,如果數(shù)據(jù)庫崩潰辜昵,可能會丟失最近 N 個事務的 binlog。
4 怎樣確保數(shù)據(jù)庫突然斷電不丟數(shù)據(jù)咽斧?
通過上面的講解堪置,只要 innodb_flush_log_at_trx_commit 和 sync_binlog 都為 1(通常稱為:雙一),就能確保 MySQL 機器斷電重啟后张惹,數(shù)據(jù)不丟失舀锨。
因此建議在比較重要的庫,比如涉及到錢的庫宛逗,設置為雙一坎匿,而你的測試環(huán)境或者正式業(yè)務不那么重要的庫(比如日志庫)可以將 innodb_flush_log_at_trx_commit 設置為0,sync_binlog 設置成大于100 的數(shù)值雷激,提高更新效率替蔬。
5 總結
本節(jié)講解了什么是事務?
所謂事務:是指一組原子性的 SQL 查詢屎暇,事務里的 SQL 要么全部執(zhí)行成功承桥,要么全部執(zhí)行失敗。
一個良好的事務處理系統(tǒng)根悼,必須具備 ACID 特性: atomicity(原子性)凶异、consistency(一致性)、 isolation(隔離性)挤巡、 durability(持久性)剩彬。
另外講解了 Redo log 和 Binlog:
Redo log:稱為重做日志,用于記錄事務操作變化玄柏,記錄的是數(shù)據(jù)被修改之后的值襟衰。
Binlog:記錄了所有變更操作,其作用有:恢復粪摘、復制瀑晒、審計等。
如果想要數(shù)據(jù)庫達到最安全的狀態(tài)徘意,可以將 innodb_flush_log_at_trx_commit 和 sync_binlog 都設置為 1苔悦。
6 問題
你工作中有遇到過丟數(shù)據(jù)的場景嗎?是什么原因導致的呢椎咧?下一章我們統(tǒng)一作答玖详。希望大家可以踴躍評論把介。謝謝大家的支持。
本文百家號首發(fā) 王者小哆啦原創(chuàng) 歡迎大家關注蟋座,收藏拗踢。