国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

MySQL InnoDB 事務已提交,數據還會丟失嗎?什么是兩階段提交?架構師必知必會高性能參數設置有哪些?

數據庫 MySQL
在 MySQL 數據庫的使用過程中,事務是一個繞不開的核心概念。我們常說“事務 ACID 特性”,其中“持久性(Durability)”明確表示:事務一旦提交,其對數據庫中數據的修改就應該是永久性的,接下來的操作或故障都不應該對其執行結果有任何影響。

在 MySQL 數據庫的使用過程中,事務是一個繞不開的核心概念。我們常說“事務 ACID 特性”,其中“持久性(Durability)”明確表示:事務一旦提交,其對數據庫中數據的修改就應該是永久性的,接下來的操作或故障都不應該對其執行結果有任何影響。

今天這篇文章,我們就從 MySQL 的底層原理出發,一步步拆解“事務提交”的完整流程,找出數據丟失的潛在風險點,同時給出可落地的解決方案。

全文約 4000 字,包含多個核心機制圖解,建議先收藏再閱讀。

一個誤區

要搞懂“提交后數據是否會丟”,首先得打破一個認知誤區:事務提交的返回結果,只是“數據庫內核確認可以完成持久化”,而非“數據已經真正寫入磁盤”

很多人以為的事務提交流程是“執行 SQL→ 修改數據 → 寫入磁盤 → 返回成功”,但這與 MySQL 的實際實現相去甚遠。

為了平衡性能和可靠性,MySQL 引入了“內存緩沖”“日志機制”等多層設計,這就導致“提交成功”和“數據持久化”之間存在時間差,而這個時間差正是數據丟失風險的根源。

在深入分析前,我們先回顧兩個基礎概念,這是理解后續內容的關鍵:

  • 事務的持久性:ACID 中的 D,理論上要求事務提交后數據永久不丟,但“永久不丟”是理想狀態,實際中需通過技術手段無限趨近這一目標。
  • MySQL 的存儲引擎:只有 InnoDB 支持事務,MyISAM 不支持。本文所有分析均基于 InnoDB 引擎。

InnoDB 事務提交的核心流程

InnoDB 之所以能在高性能下保障事務安全,核心依賴于“緩沖池(Buffer Pool)”和“重做日志(Redo Log)”兩大機制。

事務提交的全過程,本質就是這兩大機制協同工作的過程。我們先通過一張圖理清整體流程:

圖片圖片

這里我用一個 UPDATE 語句執行的例子來向你介紹事務執行過程。假如說原本 a = 3,現在要執行 UPDATE tab SET a = 5 WHERE id = 1

該流程清晰地劃分了五個核心階段。

  1. SQL 解析與事務初始化:MySQL Server 層負責接收 SQL,進行詞法分析、語法優化,生成最優的執行計劃。
  2. InnoDB 事務執行準備:InnoDB 引擎接管后,會為當前事務分配唯一 ID,并根據 WHERE 條件為需要修改的行加上排他鎖(X Lock), 防止其他事務同時修改相同行。數據加載到 buffer pool 里面。
  3. 數據修改與日志記錄(核心):這是保證事務 ACID 特性的關鍵環節。
  • 寫 Undo Log:在修改數據前,先將原始數據備份到 Undo Log 中。這確保了事務可以回滾(原子性),同時也是實現 MVCC(多版本并發控制) 的基礎,使其他事務的讀操作不受本事務寫操作的影響。
  • 修改內存數據頁:在 Buffer Pool 中直接修改數據,此時數據頁變為"臟頁"。
  • 寫 Redo Log Buffer:將數據頁的物理變化記錄到重做日志緩沖區。這是 WAL(Write-Ahead Logging) 規則的體現,即先寫日志,后刷數據。
  1. 事務提交(兩階段提交):為了確保 Binlog(用于主從復制)和 Redo Log 的一致性,MySQL 使用兩階段提交機制。
  • Prepare 階段:InnoDB 引擎根據 innodb_flush_log_at_trx_commit 決定是否 Redo Log 刷盤,并標記狀態為 prepare
  • Commit 階段:MySQL Server 寫入 Binlog 后,再將 Redo Log 標記為 commit。至此,事務才被視為真正提交,鎖被釋放。
  1. 后臺異步操作:事務提交后,被修改的"臟頁"并不會立即刷回磁盤,而是由后臺線程異步完成,這極大地提升了性能。

這張圖里藏著三個關鍵問題,也是數據丟失風險的核心:

  1. 為什么不直接把數據寫入磁盤,而要先寫緩沖池?
  2. 重做日志(Redo Log)到底是什么,為什么它的刷盤比數據刷盤更重要?
  3. 事務提交時,重做日志是“必須刷盤”還是“可以延遲刷盤”?

我們逐一拆解這三個問題,就能徹底搞懂提交后數據丟失的根源。

前置知識

update 事務執行過程,我們看到了幾個關鍵術語:bing log、undo log、redo log、buffer pool。

一起看下這些都是什么玩意。

undo log

余弦:undo log 到底是什么呢?

undo log 是指回滾日志,用一個比喻來說,就是后悔藥,它記錄著事務執行過程中被修改前的數據。

當事務回滾的時候,InnoDB 會根據 undo log 里的數據撤銷事務的更改,把數據庫恢復到原來的狀態。

在愛情的故事里,當你做錯了事,可以借助 undo log 觸發回滾技能。但是,愛情中的事可能很難執行 undo log,切記切記!

  • 對于 INSERT 來說,對應的 undo log 應該是 DELETE。
  • 對于 DELETE 來說,對應的 undo log 應該是 INSERT。
  • 對于 UPDATE 來說,對應的 undo log 也應該是 UPDATE。比如說有一個數據的值原本是 3,要把它更新成 5。那么對應的 undo log 就是把數據更新回 3。

實際上,對于 INSERT 來說,對應的 undo log 記錄了該行的主鍵。

那么后續回滾只需要根據 undo log 里面的主鍵去原本的聚簇索引里面刪掉記錄。

對于 DELETE 來說,對應的 undo log 記錄了該行的主鍵。因為在事務執行 DELETE 的時候,實際上并沒有真的把記錄刪除,只是把原記錄的刪除標記位設置成了 true

對于 UPDATE 來說,要更加復雜一些。分為兩種情況:

  • 如果沒有更新主鍵,那么 undo log 里面就記錄原記錄的主鍵和被修改的列的原值
  • 如果更新了主鍵,那么可以看作是刪除了原本的行,然后插入了一個新行。因此 undo log 可以看作是一個 DELETE 原數據的 undo log 再加上插入一個新行的 undo log。

Undo Log 的生命周期與 MVCC 的構建。

-- 示例:多版本鏈的形成
-- 事務1 (trx_id=100) 插入記錄
BEGIN;
INSERTINTO t1 (id, name, value) VALUES (1, 'A', 100);
COMMIT;

-- 事務2 (trx_id=200) 更新記錄
BEGIN;
UPDATE t1 SETvalue = 200WHEREid = 1;  -- 生成 undo log1
-- 此時版本鏈:當前記錄(trx_id=200) -> undo log1(trx_id=100)

-- 事務3 (trx_id=300) 再次更新
BEGIN;
UPDATE t1 SETvalue = 300WHEREid = 1;  -- 生成 undo log2
-- 此時版本鏈:當前記錄(trx_id=300) -> undo log2(trx_id=200) -> undo log1(trx_id=100)

redo log

InnoDB 引擎在數據庫發生更改的時候,把更改操作記錄在 redo log 里,以便在數據庫發生崩潰或出現其他問題的時候,能夠通過 redo log 來重做。

InnoDB 引擎不是直接修改了數據嗎?為什么需要 redo log?

InnoDB 引擎讀寫都不是直接操作磁盤的,而是讀寫內存里的 buffer pool,后面再把 buffer pool 里面修改過的數據刷新到磁盤里面。

這是兩個步驟,所以就可能會出現 buffer pool 中的數據修改了,但是還沒來得及刷新到磁盤數據庫就崩潰了的情況。

為了解決這個問題,InnoDB 引擎就引入了 redo log。

相當于 InnoDB 先把 buffer pool 里面的數據更新了,再寫一份 redo log。

等到事務結束之后,就把 buffer pool 的數據刷新到磁盤里面。

萬一事務提交了,但是 buffer pool 的數據沒寫回去,就可以用 redo log 來恢復。

Redo Log 的核心作用是“故障恢復”:如果服務器斷電,緩沖池中的臟頁丟失,重啟后 MySQL 會讀取 Redo Log,將所有已提交但未刷盤的操作重新執行一遍,從而恢復數據。

這就是“持久性”的底層保障——只要 Redo Log 已經刷盤,即使數據沒刷盤,數據也能恢復。

到這里,我們可以得出一個關鍵結論:事務提交后數據是否會丟,本質上取決于 Redo Log 是否已經刷盤

如果 Redo Log 沒刷盤,即使提示提交成功,斷電后數據也會丟失;如果 Redo Log 已經刷盤,即使數據沒刷盤,重啟后也能通過 Redo Log 恢復。

重做日志是 InnoDB 的核心日志,它記錄的是“數據修改的動作”,而非修改后的數據。

比如執行UPDATE user SET name='zhangsan' WHERE id=1,Redo Log 不會記錄“name 變成了 zhangsan”,而是記錄“修改了 user 表中 id=1 的記錄的 name 字段,舊值是 lisi,新值是 zhangsan”。

為什么要記錄“動作”而不是“結果”?因為“動作”更精簡,寫入速度更快。

redo log 不需要寫磁盤嗎?如果 redo log 也要寫磁盤,干嘛不直接修改數據呢?

Redo Log 的刷盤機制比數據刷盤更高效,原因有兩個:

  • 順序寫:Redo Log 文件是固定大小的循環寫入,始終是順序追加,而數據刷盤是隨機寫(要修改磁盤上的任意數據頁)。順序寫的速度遠高于隨機寫,這是 Redo Log 性能的核心優勢。
  • 小批量刷盤:Redo Log Buffer 中的日志可以批量刷盤,而數據刷盤是按數據頁(通常 16KB)刷盤,單次刷盤的數據量更大。

redo log 本身也是先寫進 redo log buffer,后面再刷新到操作系統的 page cache,或者一步到位刷新到磁盤。

InnoDB 引擎本身提供了參數 innodb_flush_log_at_trx_commit 來控制寫到磁盤的時機,里面有三個不同值。

  • 0:每秒刷新到磁盤,是從 redo log buffer 到磁盤。
  • 1:每次提交的時候刷新到磁盤上,也就是最安全的選項,InnoDB 的默認值。
  • 2:每次提交的時候刷新到 page cache 里,依賴于操作系統后續刷新到磁盤。

這時候你就應該意識到這樣一個問題,除非把 innodb_flush_log_at_trx_commit 設置成 1,否則其他兩個都有丟失的風險。

  • 0:你提交之后,InnoDB 還沒把 redo log buffer 中的數據刷新到磁盤,就宕機了。
  • 2:你提交之后,InnoDB 把 redo log 刷新到了 page cache 里面,緊接著宕機了.

在這兩個場景下,你的業務都認為事務提交成功了,但是數據庫實際上丟失了這個事務。

流程如下:

圖片圖片

舉個實際案例:某電商平臺的訂單系統,MySQL 的innodb_flush_log_at_trx_commit配置為 2。

某次服務器突然斷電,重啟后發現有 10 分鐘內的訂單數據丟失,造成了不小的損失。

事后排查發現,就是因為這 10 分鐘內的訂單事務雖然提交成功,但 Redo Log 還在 OS Cache 中,沒刷到磁盤,斷電后 OS Cache 中的數據丟失,無法恢復。

binlog

Binlog(Binary Log)是 MySQL 的二進制日志,它記錄了所有對數據庫的數據變更操作。它是 MySQL Server 級別的日志,也就是說所有引擎都有。

想象一下,它是 MySQL 的"行車記錄儀",完整記錄了數據庫的每一個變化瞬間。

圖片圖片

在事務執行過程中,寫入 binlog 的時機有點巧妙。它和 redo log 的提交過程結合在一起稱為 MySQL 的兩階段提交。

  • Prepare(準備)階段:存儲引擎(如 InnoDB)將事務的redo log寫入磁盤,并將事務狀態標記為TRX_STATE_PREPARED(或PREPARE)。
  • Commit(提交)階段:此階段又可細分為關鍵步驟:

寫入 Binlog:首先將事務的binlog數據寫入磁盤文件。此時數據可能還在操作系統的頁面緩存(Page Cache)中。

刷盤 Binlog:根據sync_binlog參數設置,決定何時將binlog從緩存強制寫入磁盤,這是保證持久性的關鍵一步。

標記 Commit:最后,存儲引擎將redo log中該事務的狀態標記為COMMIT。值得注意的是,只要binlog已安全落盤,即使此步驟因崩潰未完成,事務仍被視為已提交。

事務執行過程,binlog 與 redo log 二階段提交和崩潰恢復機制流程如下圖所示:

圖片圖片

如果 redo log Prepare 執行完畢后,binlog 已經寫成功了,那么即便 redo log 提交失敗,MySQL 也會認為事務已經提交了。

如果 binlog 沒寫成功,那么 MySQL 就認為提交失敗了。

比較簡單的記憶方式就是看 binlog 寫成功了沒有

binlog 本身有一些完整性校驗的規則,所以在 MySQL 看來,寫 binlog 要么成功,要么失敗,不存在中間狀態。

binlog 也有刷新磁盤的問題,不過你可以通過 sync_binlog 參數來控制它。

  • 0:由操作系統決定,寫入 page cache 就認為成功了。0 也是默認值,這個時候數據庫的性能最好。
  • N:每 N 次提交就刷新到磁盤,N 越小性能越差。如果 N = 1,那么就是每次事務提交都把 binlog 刷新到磁盤。

總結

為了在保證數據安全和高性能之間取得平衡,有幾個關鍵參數可以調整;

  • sync_binlog:控制 binlog 刷盤策略。設為 1 最安全(每次提交都刷盤),但性能開銷最大;設為大于 1 的值可提升性能,但宕機可能丟失最近 N 個事務的 binlog。
  • innodb_flush_log_at_trx_commit:控制 redo log 刷盤策略。設為 1 最安全(每次提交都刷盤);設為 0 或 2 可提升性能,但存在數據丟失風險。

對數據不丟失、一致性要求高的業務,你可以考慮調整 sync_binlog 的值為 1。

另外一個是性能優先,能夠容忍一定數據丟失的。

那么你可以考慮將 innodb_flush_log_at_trx_commit 調整為 0 或者 2,同時還可以把 sync_binlog 調整為比較大的值,比如說調到 100。

責任編輯:武曉燕 來源: 碼哥跳動
相關推薦

2022-12-21 19:04:35

InnoDBMySQL

2024-05-21 14:12:07

2022-03-28 10:44:51

MySQL日志存儲

2023-07-26 09:24:03

分布式事務分布式系統

2023-12-05 09:33:08

分布式事務

2018-10-29 08:44:29

分布式兩階段提交事務

2024-12-06 07:10:00

2025-06-19 08:03:03

2025-06-10 08:02:15

2023-01-18 10:35:49

MySQL數據庫

2024-01-26 08:18:03

2023-11-29 07:47:58

DDIA兩階段提交

2024-07-22 08:57:58

2025-05-16 07:46:11

分布式事務服務

2025-05-26 00:00:05

2022-04-11 00:21:32

MySQL事務數據庫

2022-07-27 08:52:10

MySQL二階段提交

2020-02-03 12:12:28

MySQL數據庫SQL

2025-11-17 01:22:00

2020-07-10 07:58:14

Linux
點贊
收藏

51CTO技術棧公眾號

国产在线一二三区| 欧洲亚洲在线| 亚洲欧美文学| 夜夜嗨av色综合久久久综合网| 116极品美女视频在线观看| 日本女优在线视频一区二区| 91国产视频在线| 国产精品原创| 欧美日韩在线不卡| 欧美艹逼视频| 91社区在线播放| 杨幂一区欧美专区| 亚洲人人精品| 51国产成人精品午夜福中文下载| 国产伦乱精品| 中文字幕日韩有码| 欧美亚洲系列| 欧美一区二区啪啪| 成年人在线观看| 香蕉影视欧美成人| 91福利电影| 国产清纯白嫩初高生在线观看91| 中文字幕の友人北条麻妃| 国产午夜精品一区二区三区欧美 | 麻豆成人91精品二区三区| 亚洲综合中文字幕在线| 国产欧美日韩精品一区二区三区| 久久久精品日本| 久久三级毛片| 亚洲日韩第一页| 女海盗2成人h版中文字幕| 日韩你懂的电影在线观看| 阿v免费在线观看| 在线免费观看日本欧美| 四虎影视在线观看2413| 欧美日韩另类字幕中文| 成人精品3d动漫| 亚洲欧美综合网| 一本色道久久亚洲综合精品蜜桃 | 国产精选一区二区三区| 亚洲色图国产精品| 欧美日韩一区二区欧美激情| a级黄色一级片| 国产精品高清一区二区| 欧美精品一区二区三区一线天视频 | 欧美日韩国产免费一区二区 | 欧美日韩视频第一区| 北条麻妃视频在线| 亚洲国产一区二区a毛片| 麻豆福利在线观看| 国产精品普通话| 91美女片黄在线观看91美女| 欧美精品v日韩精品v国产精品| 日本vs亚洲vs韩国一区三区| 精品少妇人妻av一区二区| 激情伊人五月天久久综合| 亚洲激情第一页| 免费国产在线观看| 美女网站在线看| 福利在线一区| 亚洲一区二区三区四区在线免费观看 | 黄页视频在线观看| 久久一区二区三区四区| 免费在线精品视频| 成人综合激情网| h网站在线播放| 欧美久久高跟鞋激| 麻豆视频在线观看免费网站| 色吊一区二区三区| 激情亚洲成人| 97久久精品午夜一区二区| 国产精品videosex极品| 欧美一级黄色网| 欧美电影一二区| 免费看污久久久| 久久99精品视频| 国产免费成人在线| 亚洲国产成人porn| 国产一级在线观看| 精品成人佐山爱一区二区| 成人1区2区| 久久久久久久亚洲精品| 91麻豆精品国产91久久久平台| 国产精品手机在线| 国产成人av一区二区三区在线 | 色喇叭免费久久综合网| 国产传媒一区| 成人午夜av电影| 在线观影网站| 亚洲国产成人精品女人久久久 | 国产免费黄色av| 亚洲自拍偷拍九九九| 色yeye免费人成网站在线观看| 中文字幕最新精品| 你微笑时很美电视剧整集高清不卡| 国产日韩亚洲精品| 国产亚洲福利社区一区| 日本在线免费播放| 欧美美女15p| 国内精品久久久久久久97牛牛| 99在线精品免费视频 | 欧美 国产 精品| 亚洲精品中文在线| 亚洲h片在线看| 青青青国产精品一区二区| 午夜亚洲伦理| 艹b视频在线观看| 91精品国产色综合久久久蜜香臀| 视频在线亚洲| 国产66精品久久久久999小说| 91丨porny丨最新| 日本中文字幕在线视频| 国产精品麻豆一区二区| 国产三区在线观看| 欧美激情综合色| 日韩高清不卡在线| 成人免费淫片在线费观看| 亚洲电影免费观看高清| 国产videos久久| 欧美亚洲色图视频| 色婷婷综合中文久久一本| 中文字幕av一区二区三区四区| 久久精品丝袜高跟鞋| 亚洲乱码日产精品bd| 天堂av在线| 亚洲综合大片69999| 久久久91精品国产一区二区三区| 国产精品麻豆一区二区三区| 久久久久久久久网| 日本网站在线观看一区二区三区| www.成人三级视频| 天天综合天天做天天综合| 蜜桃av综合| 黑巨人与欧美精品一区| 亚洲欧美色婷婷| 99在线精品免费视频九九视| 亚洲精品中文字幕无码蜜桃| 日韩电影中文字幕在线观看| 91久久国产| 国产美女特级嫩嫩嫩bbb片| 亚洲视频第一页| 日韩高清在线观看| 国产系列在线观看| 国产精品大片wwwwww| 久久精品网站免费观看| 97人人做人人爽香蕉精品| 亚洲精品9999| 日韩视频国产视频| 亚洲日本免费| 欧美91精品久久久久国产性生爱| 91av国产在线| 久久久亚洲国产美女国产盗摄| 国产在视频一区二区三区吞精| 日韩美女视频中文字幕| 98视频在线噜噜噜国产| 一级女性全黄久久生活片免费| 岛国毛片av在线| 黄色一级片在线看| 日本一区二区免费看| 奇米888四色在线精品| 日本国产一区| 国产视频观看一区| 国产精品三级av| 久久中文字幕一区二区| 精品无码国模私拍视频| 亚洲免费一在线| 激情综合网av| 精品极品在线| 最新精品视频| 精品视频在线播放| 国产精品88av| 久久91导航| 国产男女在线观看| 精品国产一区二区三区久久久狼 | 欧美,日韩,国产在线| 亚洲精品在线91| 国产黄色精品视频| 日韩中文视频| 无遮挡又爽又刺激的视频| 久久视频在线播放| 国产精品视频观看| 国产精品欧美三级在线观看| 深夜福利视频在线免费观看| 99精品国产高清一区二区| 欧美一卡二卡三卡| 久久99精品久久久久| 欧美三级电影网址| 亚洲一级片免费| 成人久久久久久久| 欧美系列在线观看| 毛片av一区二区| 欧美一区二区视频17c| 国产日韩欧美成人| 成人免费网站在线看| 色激情天天射综合网| 国产成人av电影在线| 日本大香伊一区二区三区| 天天综合色天天综合色h| 丁香花电影在线观看完整版| 大地资源网在线观看免费官网|