1. 程式人生 > >MySQL5.6 Online DDL

MySQL5.6 Online DDL

占用 鎖表 修改 原則 構造 ODB 基本 很多 mage

MySQL5.6 Online DDL

簡單介紹

ddl包含了copy和inplace方式,對於不支持online的ddl操作采用copy方式。對於copy方式,copy過程中全程鎖表,不允許寫(rename階段會禁止讀寫),比如修改表字段的類型,包括修改長度,對於inplace方式,mysql內部以是否修改記錄格式為基準也分為兩類,一類需要重建表(重新組織記錄,重建過程中會建立臨時ibd文件),比如添加索引、添加/刪除列、修改列NULL/NOT NULL屬性等;另外一類是只需要修改表的元數據,比如刪除索引、修改列名、修改列默認值、修改列自增值等。MySQL將這兩類方式分別稱為rebuild方式和no-rebuild方式。

online ddl主要包括3個階段,prepare階段,ddl執行階段,commit階段,rebuild方式比no-rebuild方式實質多了一個ddl執行階段,prepare階段和commit階段類似。

prepare階段
  1. 創建新的臨時frm文件(MySQL server層建的)
  2. 升級MDL_SHARED_UPGRADABLE到EXCLUSIVE-MDL鎖,禁止讀寫
  3. 根據alter類型,確定執行方式(copy,online-rebuild,online-norebuild)
  4. 更新數據字典的內存對象
  5. 分配row_log對象記錄增量
  6. 生成新的臨時ibd文件

此階段主要是innodb引擎做一些校驗,分配空間,初始化等操作,時間不長,對於用戶感覺不出來禁止讀寫

ddl執行階段
  1. 降級EXCLUSIVE-MDL鎖到MDL_SHARED_UPGRADABLE,允許讀寫
  2. 掃描old_table的聚集索引每一條記錄rec
  3. 遍歷新表的聚集索引和二級索引,逐一處理
  4. 根據rec構造對應的索引項
  5. 將構造索引項插入sort_buffer塊
  6. 將sort_buffer塊插入新的索引
  7. 處理ddl執行過程中產生的增量(僅rebuild類型需要)
commit階段
  1. 升級MDL_SHARED_UPGRADABLE到EXCLUSIVE-MDL鎖,禁止讀寫
  2. 重做最後row_log中最後一部分增量
  3. 更新innodb的數據字典表
  4. 提交事務(刷事務的redo日誌)
  5. 修改統計信息
  6. rename臨時idb文件,frm文件
  7. 變更完成

對於norebuid模式(如刪除索引),InnoDB二級索引只需要更新內部視圖,並標記這個索引的空間可用,去掉數據庫元數據上該索引的定義即可,都是在原表上操作,不需要重建與copy數據,所以速度非常快,基本可以忽略阻塞讀寫的時間

row_log說明
  1. Row Log中記錄的是Online創建索引期間,原表上的DML操作這些操作包括:ROW_OP_INSERT;ROW_OP_DELETE_MARK等
  2. Row Log以Block的方式存儲,若DML較多,那麽Row Logs可能會占用多個Blocks。row_log_t結構中包含兩個指針:head與tail,head指針用於讀取Row Log,tail指針用於追加寫新的Row Log
  3. 在重用Row Log時,算法遵循一個原則:盡量減少索引樹加鎖的時間(索引樹加X鎖,也意味著表上禁止了新的DML操作)
索引樹加鎖的場景
  1. 在重用Row Log跨越新的Block時,需要短暫加鎖;
  2. 若應用的Row Log Block是最後一個Block,那麽一直加鎖應用最後一個Block,由於禁止了新的DML操作,因此此 Block應用完畢,新索引記錄與聚簇索引達到一致狀態,重用階段結束;
  3. 在應用中間Row Log Block上的row log時,無需加鎖,新的DML操作仍舊可以進行,產生的row log記錄到最後一個Row Log Block之上;
源碼分析

技術分享圖片

雖然畫了上面的圖,但是裏面的細節還是有很多的不懂,不明白,還是只能知道大概的流程,對於每一個點都是一個很深的知識點,commit階段也還沒有整理,待補

MySQL5.6 Online DDL