?InnoDB 表包含:表結(jié)構(gòu)和數(shù)據(jù)宰翅。8.0 前,表結(jié)構(gòu)存在.frm 文件爽室。8.0 版本汁讼,表結(jié)構(gòu)(占用空間小)放系統(tǒng)數(shù)據(jù)表肮之。
一掉缺、為什么刪除表數(shù)據(jù),表空間不能回收戈擒?
1.參數(shù)innodb_file_per_table
控制表數(shù)據(jù)在? 共享表空間? 或 單獨(dú)文件
????1)OFF 眶明,數(shù)據(jù)共享表空間,跟數(shù)據(jù)字典一起筐高;表刪掉搜囱,空間不會回收。
????2)?ON (默認(rèn))柑土,在 .ibd 文件中蜀肘;不需要時, drop table直接刪除
刪除行稽屏,數(shù)據(jù)被刪除扮宠,沒回收空間
2.數(shù)據(jù)刪除流程
索引的示意圖B+ 樹,刪掉 R?標(biāo)記為刪除狐榔。插入ID 300 和 600?復(fù)用坛增。磁盤文件大小不變
InnoDB 數(shù)據(jù)按頁存儲,刪掉頁上所有薄腻,整個頁復(fù)用
3.數(shù)據(jù)頁 跟 記錄復(fù)用 是不同
delete 只標(biāo)記“可復(fù)用”收捣,沒被用空間,像“空洞”
? ??記錄復(fù)用:插入 ID = 800 庵楷,不能復(fù)用
? ??整頁:1)從 B+ 樹里摘掉罢艾,可復(fù)用任何位置楣颠。2)兩頁利用率都小,合到一個咐蚯,另一頁標(biāo)記可復(fù)用
4童漩、插入也會造成空洞
更新:刪舊值,插新仓蛆,也會造空洞睁冬。? ? ?按索引遞增插(緊湊),隨機(jī)插(頁分裂)
例:page A?已滿看疙,再插豆拨,申請新頁?page B 保存。頁分后能庆,A?末尾留空洞(實(shí)際上不止 1 個記錄位空洞)
二施禾、?回收空間:重建表
新建表 B(表 A?相同結(jié)構(gòu)),A 中讀出插入 B (按主鍵 ID 遞增)
B 替換 A收縮表:A 上空洞搁胆, B 新建不存在(因?yàn)橹麈I索引緊湊)
? ??alter table A engine=InnoDB 重建表弥搞。 5.5 前,B 不需創(chuàng)建渠旁,MySQL 自動完成轉(zhuǎn)存數(shù)據(jù)攀例、交換表名、刪除舊表的操作
? ??臨時表插入數(shù)據(jù)(時間最多)顾腊,新寫入到A 丟失粤铭。DDL中A 中不能更新(非Online)。
2杂靶、Online DDL(?可做增刪改)重建表流程:
1.? 建臨時文件梆惯,掃描表 A 主鍵所有數(shù)據(jù)頁
2.? A 記錄生成 B+ 樹,存臨時文件
3.? 生成臨時文件過程中吗垮, A 操作記錄日志文件(row log)中垛吗,state2 狀態(tài);
4. 臨時文件生成后烁登,日志文件操作應(yīng)用臨時文件怯屉,邏輯數(shù)據(jù)上與A 相同,state3 狀態(tài)饵沧;
5.? 臨時文件替換表 A蚀之。
第 6 篇《全局鎖和表鎖 :給表加個字段怎么索這么多阻礙?》留言說捷泞,DDL 之前拿 MDL 寫鎖,還能叫 Online DDL 嗎寿谴?
alter 啟動獲 MDL 寫鎖锁右,拷貝數(shù)據(jù)前退化成讀鎖(圖 4?)。
????為什么退化?實(shí)現(xiàn) Online咏瑟,MDL 讀鎖不阻塞增刪改操作
????不解鎖拂到,保護(hù)自己,禁止其他線程做 DDL
拷貝數(shù)據(jù)最耗時码泞,可接受增刪改兄旬。 DDL 過程,鎖時間非常短余寥,可認(rèn)為 Online?
上述重建方法都掃描原表领铐、構(gòu)建臨時文件。大表消耗 IO 和 CPU 資源宋舷。線上小心控制操作時間绪撵。用 GitHub 開源gh-ost?做安全
3.Online 和inplace
inplace?和DDL 有關(guān)、容易和Online混淆?
圖 3 表 A 中數(shù)據(jù)導(dǎo)出來放 tmp_table(臨時表)祝蝠, server 層創(chuàng)建音诈。
inplace:重建數(shù)據(jù)放“tmp_file”里(圖 4?),InnoDB 內(nèi)部創(chuàng)建绎狭。DDL 在 InnoDB 內(nèi)部完成细溅。server 層“原地”操作(沒把數(shù)據(jù)挪動到臨時表)。
例1:1TB 的表儡嘶,磁盤間 1.2TB喇聊,不能做 inplace? DDL ,tmp_file 占臨時空間社付。
alter table t engine=InnoDB承疲,隱含意思:
alter table t? engine=innodb, ALGORITHM=inplace;
對應(yīng)強(qiáng)制拷貝表(圖 3)用法是:
alter table t? engine=innodb,ALGORITHM=copy;
例2:給 InnoDB 表字段加全文索引(過程 inplace ,非 Online?)
alter table t add? FULLTEXT(field_name);
兩個邏輯關(guān)系是:
1.? DDL 過程如 Online 鸥咖,一定 inplace 燕鸽;
2.? 反過來未必, inplace 的 DDL啼辣,可能不是 Online 啊研。如:添加全文索引(FULLTEXT index)和空間索引 (SPATIAL index) 。
4.analyze table 和 alter table 鸥拧、optimize table重建表區(qū)別
alter table t engine = InnoDB(recreate)圖? 4 党远;
analyze table t 表索引重新統(tǒng)計(jì),沒修改數(shù)據(jù)富弦,過程加了 MDL 讀鎖沟娱;
optimize table t 等于 recreate+analyze。recreate幾乎全新腕柜,analyze必要小極端情況用
小結(jié)
數(shù)據(jù)庫中收縮表空間方法济似。
收縮表矫废,delete 數(shù)據(jù)表文件大小不變,alter table 重建表文件變小
重建表兩種實(shí)現(xiàn):Online DDL業(yè)務(wù)低峰期使用
思考題
“收縮表空間砰蠢,適得其反”什么原因 蓖扑?
表 t 1TB;執(zhí)行 alter table tengine=InnoDB台舱;變成 1.01TB律杠。
答:表本身沒空洞(如剛重建表)。DDL 時竞惋,剛好外部 DML 執(zhí)行柜去,引入新空洞。
重建表后不是“最”緊湊:重建表時碰声,InnoDB 不會把整張表占滿诡蜓,留1/16 給后續(xù)更新。
如:1.? 表 t 重建胰挑; 插入數(shù)據(jù)蔓罚,掉預(yù)留空間;2.? 再重建表 t瞻颂,上面現(xiàn)象豺谈。
評論1
1.Truncate 會釋放表空間嗎?理解為drop+create
2.重建表沒更新贡这,有可能產(chǎn)生頁分裂和空洞茬末?Online 沒有
3.相對 Server層沒有新建臨時表,就是 inplace盖矫,怎么判斷是不是相對 Server 層沒有新建臨時表丽惭?
命令執(zhí)行后影響行數(shù),沒有新建臨時表辈双,新建行數(shù)0
4.分布式ID(雪花算法生成的ID)生成的索引和自增ID责掏。性能一樣
雪花算法生成ID:越來越大,但不逐漸遞增湃望,長度bitint换衬。
評論2
將 alter 顯式放到事務(wù)里 ,事務(wù)不提交 证芭, 另一事務(wù)查詢到alter 操作后表結(jié)構(gòu) 是否打破了 mvcc 瞳浦?
alter table 默認(rèn)提交前面事務(wù),自己獨(dú)立執(zhí)行