MySQL 資料刪除之後表檔案不變

2021-10-12 16:39:39 字數 2215 閱讀 5871

在 mysql 8.0 版本以前,表結構是存在以.frm 為字尾的檔案裡。而 mysql 8.0 版本,則已經允許把錶結構定義放在系統資料表中了。

引數innodb_file_per_table

引數設定為 off 表示的是,表的資料放在系統共享表空間,也就是跟資料字典放在一起;

引數設定為 on 表示的是,每個 innodb 表資料儲存在乙個以 .ibd 為字尾的檔案中。

從 mysql 5.6.6 版本開始,它的預設值就是 on 了。

建議不論使用 mysql 的哪個版本,都將這個值設定為 on。因為,乙個表單獨儲存為乙個檔案更容易管理,而且在你不需要這個表的時候,通過 drop table 命令,系統就會直接刪除這個檔案。

假設,在乙個資料頁上要在300和600之間刪除乙個值,如果之後要再插入乙個 id 在 300 和 600 之間的記錄時,可能會復用這個位置。記錄的復用,只限於符合範圍條件的資料。

假設,某頁上的記錄全部刪除,整個資料頁就可以被復用了。當整個頁從 b+ 樹裡面摘掉以後,可以復用到任何位置。

如果相鄰的兩個資料頁利用率都很小,系統就會把這兩個頁上的資料合到其中乙個頁上,另外乙個資料頁就被標記為可復用。

進一步地,如果我們用 delete 命令把整個表的資料刪除呢?結果就是,所有的資料頁都會被標記為可復用。但是磁碟上,檔案不會變小。

delete 命令其實只是把記錄的位置,或者資料頁標記為了「可復用」,但磁碟檔案的大小是不會變的。

實際上,不止是刪除資料會造成空洞,插入資料也會。在隨機插入資料的時候,可能會引起頁**,從而導致某個頁不能填充滿,也就是所謂的空洞。

解決空洞,收縮空間的方法就是重建表。

你可以使用 alter table a engine=innodb 命令來重建表。在整個 ddl 過程中,表 a 中不能有更新。也就是說,這個 ddl 不是 online 的。

mysql 5.6 版本開始引入的 online ddl。

引入了 online ddl 之後,重建表的流程:

1、建立乙個臨時檔案,掃瞄表 a 主鍵的所有資料頁;

2、用資料頁中表 a 的記錄生成 b+ 樹,儲存到臨時檔案中;

3、生成臨時檔案的過程中,將所有對 a 的操作記錄在乙個日誌檔案(row log)中,對應的是圖中 state2 的狀態;

4、臨時檔案生成後,將日誌檔案中的操作應用到臨時檔案,得到乙個邏輯資料上與表 a 相同的資料檔案,對應的就是圖中 state3 的狀態;

5、用臨時檔案替換表 a 的資料檔案。

alter 語句在啟動的時候需要獲取 mdl 寫鎖,但是這個寫鎖在真正拷貝資料之前就退化成讀鎖了。

為什麼要退化呢?為了實現 online,mdl 讀鎖不會阻塞增刪改操作。

而對於乙個大表來說,online ddl 最耗時的過程就是拷貝資料到臨時表的過程,這個步驟的執行期間可以接受增刪改操作。所以,相對於整個 ddl 過程來說,鎖的時間非常短。對業務來說,就可以認為是 online 的。

推薦你使用 github 開源的gh-ost來做。

根據表 a 重建出來的資料是放在「tmp_file」裡的,這個臨時檔案是 innodb 在內部建立出來的。整個 ddl 過程都在 innodb 內部完成。對於 server 層來說,沒有把資料挪動到臨時表,是乙個「原地」操作,這就是「inplace」名稱的**~~~~~這個理解我認為其實是比較扯的。

因為畢竟資料或資料頁的位置要發生變化,怎麼能以參考「對於 server 層來說沒有把資料挪動到臨時表」就稱為原地操作呢?

alter table t engine=innodb,其實隱含的意思是:alter table t engine=innodb,algorithm=inplace;

拷貝表的方式了,用法是:alter table t engine=innodb,algorithm=copy;

給表增加全文索引:alter table t add fulltext(field_name);

從 mysql 5.6 版本開始,alter table t engine = innodb

(也就是 recreate)預設的就是上面圖 4 的流程了;

analyze table t其實不是重建表,只是對錶的索引資訊做重新統計,沒有修改資料,這個過程中加了 mdl 讀鎖;

optimize table t等於 recreate+analyze。

MySQL刪除表資料

在mysql中有兩種方法可以刪除資料,一種是delete語句,另一種是truncate table語句。delete語句可以通過where對要刪除的記錄進行選擇。而使用truncate table將刪除表中的所有記錄。因此,delete語句更靈活。如果要清空表中的所有記錄,可以使用下面的兩種方法 d...

mysql 刪除表 命令 MySQL 刪除資料表

mysql 刪除資料表 mysql中刪除資料表是非常容易操作的,但是你再進行刪除表操作時要非常小心,因為執行刪除命令後所有資料都會消失。語法以下為刪除mysql資料表的通用語法 drop table table name 在命令提示視窗中刪除資料表 在mysql 命令提示視窗中刪除資料表sql語句為...

mysql 中文刪除表 MySQL 刪除資料表

mysql 刪除資料表 mysql中刪除資料表是非常容易操作的,但是你再進行刪除表操作時要非常小心,因為執行刪除命令後所有資料都會消失。語法以下為刪除mysql資料表的通用語法 drop table table name 在命令提示視窗中刪除資料表 在mysql 命令提示視窗中刪除資料表sql語句為...