首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

為什麼 MySQL 回滾事務也會導致 IBD 文件增大?TEXT 欄位特殊存儲機制深度解析

     編輯:MySQL 綜合教學

為什麼 MySQL 回滾事務也會導致 IBD 文件增大?

一、現象復現

CREATE TABLE tb1 (
  id INT AUTO_INCREMENT PRIMARY KEY,
  webtext TEXT,
  tp VARCHAR(2),
  se INT
) ENGINE=InnoDB;

START TRANSACTION;
INSERT INTO tb1 VALUES (3, REPEAT('a', 65000), 'x', 1);
-- COMMIT;
ROLLBACK;

文件大小變化:

  • 插入前:98,304 bytes
  • INSERT 後(未提交):131,072 bytes (+32,768)
  • ROLLBACK 後:163,840 bytes (+32,768)

IBD 文件大小變化截圖

二、根因:TEXT/BLOB 獨立存儲對象

MySQL 手冊:Each BLOB or TEXT value is represented internally by a separately allocated object. This is in contrast to all other data types, for which storage is allocated once per column when the table is opened.
  • TEXT/BLOB **不在聚簇索引頁中直接存儲**,而是分配**獨立的溢出頁**
  • 對這些列的寫入(INSERT/UPDATE)**直接落盤**,不經過 Buffer Pool 延遲刷新
  • 因此 INSERT 瞬間分配溢出頁 → IBD 增大

三、ROLLBACK 為何再增大?

  1. ROLLBACK 需邏輯刪除已插入行
  2. InnoDB 刪除操作 = **標記刪除標志位** + 寫入 Undo Log
  3. 對於 TEXT 列,刪除標記同樣需要**分配一個新的溢出頁對象**來存儲「已刪除版本」的元數據
  4. 故再次分配 32,768 bytes(InnoDB 溢出頁最小分配單元 = 32KB = 2^15)

四、為什麼是 32,768 bytes?

  • TEXT 最大 65,535 字節
  • InnoDB 溢出頁分配粒度:**32 KB**(佔用一個完整頁或頁組)
  • REPEAT('a', 65000) ≈ 65 KB → 需 2 個 32KB 頁 = 64 KB,但實測單次增長 32 KB,推測為壓縮或首頁共享機制
  • 若插入 REPEAT('a', 65535):INSERT 增長 65,536,ROLLBACK 再增 32,768

五、非 TEXT 列驗證

同表中 VARCHAR(2)、INT 列的 INSERT + ROLLBACK **不會**導致 IBD 增大,證實僅 TEXT/BLOB 觸發。

六、總結與啟示

操作TEXT/BLOB IBD 變化普通列 IBD 變化
INSERT+32KB (分配溢出頁)無變化 (Buffer Pool 延遲刷新)
ROLLBACK+32KB (分配刪除標記頁)無變化
COMMIT空間可被 Purge 線程回收空間可被回收
啟示: 大量 TEXT/BLOB 寫入+回滾場景(如導入腳本失敗重試)會導致 IBD 文件快速膨脹,需關注 innodb_file_per_table、定期 OPTIMIZE TABLE 或 ALTER TABLE ... ENGINE=InnoDB 回收空間。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved