這篇文章為大家帶來了關於mysql的相關知識,其中主要整理了解決delete大量資料後空間不釋放的相關問題,MySQL 中insert 與update 都可能導致頁分裂,這樣就存在碎片,下面一起來看一下,希望對大家有幫助。
推薦學習:mysql影片教學
# MySQL 的幾個片段整理方案總結(解決delete大量資料後空間不釋放的問題)
1.背景知識?
1.1 為什麼會有碎片?
-
MySQL 中insert 與update 都可能導致頁分裂,這樣就存在碎片。
對於大量的UPDATE,也會產生檔案碎片化, Innodb的最小實體儲存分配單位是頁(page),而UPDATE也可能導致頁分裂(page split),頻繁的頁分裂,頁會變得稀疏,並且被不規則的填充,所以最終資料會有碎片。
-
delete 語句其實只是給資料打個標記,並且記錄到一個鍊錶中,這樣就形成了留白空間。
在InnoDB中,刪除一些行,這些行只是被標記為“已刪除”,而不是真的從索引中物理刪除了,因而空間也沒有真的被釋放回收。 InnoDB的Purge執行緒會異步的來清理這些沒用的索引鍵和行。
當執行插入操作時,MySQL會嘗試使用空白空間,但如果某個空白空間一直沒有被大小合適的資料佔用,仍然無法將其徹底佔用,就形成了碎片;
-
總結:
表的增刪改操作,可能會造成資料空洞的,當資料表進行大量的增刪改操作後,數據空洞存在的可能性比較大。
-
MySQL刪除資料幾種情況以及是否釋放磁碟空間:
- drop ,truncate 立刻釋放磁碟空間,不管是Innodb和MyISAM ;
- truncate table其實有點類似drop table 然後creat,只不過這個create table 的過程做了優化,比如表結構檔之前已經有了等等。所以速度上應該是接近drop table的速度;
- delete from table_name刪除表的全部資料,對於MyISAM 會立刻釋放磁碟空間(應該是做了特別處理,也比較合理),InnoDB 不會釋放磁碟空間;
- 對於delete from table_name where xxx; 帶條件的刪除, 不管是innodb還是MyISAM都不會釋放磁碟空間;
- #delete操作以後使用optimize table table_name 會立刻釋放磁碟空間。不管是innodb還是myisam 。所以要達到釋放磁碟空間的目的,delete以後執行optimize table 操作。
- delete from表以後雖然未釋放磁碟空間,但下次插入資料的時候,仍然可以使用這部分空間。
1.2 片段所帶來的問題
當MySQL掃描資料時,它掃描的物件實際上是列表的容量需求上限,也就是資料被寫入的區域中處於峰值位置的部分;
MySQL資料庫中的表在進行了多次delete、update和insert後,表空間會出現碎片。定期進行表空間整理,消除碎片可以提高存取表空間的效能。
這種碎片不僅額外增加了儲存代價,同時也因為資料碎片化降低了表格的掃描效率。
片段若不整理,那麼可能會長期佔據磁碟空間,導致磁碟使用率越來越高。
2. 如何清理碎片?
修復問題的前提是要先找到問題,這樣才能對症下藥。
2.1. 查看表格的碎片狀況
-
查看資料庫中每個存在碎片的表
mysql> select concat('optimize table ',table_schema,'.',table_name,';'),data_free,engine from information_schema.tables where data_free>0 and engine !='MEMORY'; +-----------------------------------------------------------+-----------+--------+ | concat('optimize table ',table_schema,'.',table_name,';') | DATA_FREE | ENGINE | +-----------------------------------------------------------+-----------+--------+ | optimize table abc.t_user_answer; | 2097152 | InnoDB | | optimize table mysql.time_zone_transition; | 4194304 | InnoDB | | optimize table mysql.time_zone_transition_type; | 4194304 | InnoDB | | optimize table mysql.user; | 4194304 | InnoDB | 。。。。
-
#查看指定表的碎片情況
mysql> show table status like 't_user'\G *************************** 1. row *************************** Name: t_user Engine: InnoDB Version: 10 Row_format: Dynamic Rows: 4333 Avg_row_length: 589 Data_length: 2555904 Max_data_length: 0 Index_length: 2719744 Data_free: 4194304 Auto_increment: NULL Create_time: 2021-11-19 10:13:31 Update_time: 2022-04-20 14:28:42 Check_time: NULL Collation: utf8mb4_general_ci Checksum: NULL Create_options: Comment: 1 row in set (0.00 sec)
Data_free: 4194304 就代表碎片的byte數。如果經常刪改資料表,會造成大量的Data_free 頻繁 刪除記錄 或修改有可變長度欄位的表。
-
找到碎片化最嚴重的表格
SELECT table_schema, TABLE_NAME, concat(data_free/1024/1024, 'M') as data_free FROM `information_schema`.tables WHERE data_free > 3 * 1024 * 1024 AND ENGINE = 'innodb' ORDER BY data_free DESC
2.2 清理碎片(回收空間)的方法
官方文件參考
#
通常有这几种做法
- alter table tb_test engine=innodb; (本质上是 recreate)
- optimize table tb_test; (本质上是 recreate,但是在不同创建下会有区别)
- ALTER TABLE tablename FORCE (在InnoDB表中等价于 alter table tb_test engine=innodb; )
- mysqlcheck 批量表空间优化
- gh-ost/pt-osc
- pt-online-schema-change (本质上也是 先备份旧表数据,然后 truncate 旧表)
1. alter table tb_test engine=innodb 原理介绍
这其实是一个NULL操作,表面上看什么也不做,实际上重新整理碎片了.当执行优化操作时,实际执行的是一个空的 ALTER 命令,但是这个命令也会起到优化的作用,它会重建整个表,删掉未使用的空白空间.
Running ALTER TABLE tbl_name ENGINE=INNODB on an existing InnoDB table performs a “null” ALTER TABLE operation, which can be used to defragment an InnoDB table, as described in Section 15.11.4, “Defragmenting a Table”. Running ALTER TABLE tbl_name FORCE on an InnoDB table performs the same function.
MySQL5.6 开始采用 Inplace 方式重建表,Alter 期间,支持 DML 查询和更新操作,语句为 alter table t engine=innodb, ALGORITHM=inplace;之所以支持 DML 更新操作,是因为数据拷贝期间会将 DML 更新操作记录到 Row log 中。 重建过程中最耗时的就是拷贝数据的过程,这个过程中支持 DML 查询和更新操作,对于整个 DDL 来说,锁时间很短,就可以近似认为是 Online DDL。 执行过程: 1、获取 MDL(Meta Data Lock)写锁,innodb 内部创建与原表结构相同的临时文件 2、拷贝数据之前,MDL 写锁退化成 MDL 读锁,支持 DML 更新操作 3、根据主键递增顺序,将一行一行的数据读出并写入到临时文件,直至全部写入完成。并且,会将拷贝期间的 DML 更新操作记录到 Row log 中 4、上锁,再将 Row log 中的数据应用到临时文件 5、互换原表和临时表表名 6、删除临时表
2. optimize table xxx;
OPTIMIZE TABLE语句可以重新组织表、索引的物理存储,减少存储空间,提高访问的I/O效率。类似于碎片整理功能。
MySQL可以通过optimize table
语句释放表空间,重组表数据和索引的物理页,减少表所占空间和优化读写性能
-
使用语法
OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_n说ame [, tbl_name] …
- 对于主从架构, LOCAL 参数可以让这个过程不写入 binlog ,这样在主库上执行时就不会同步给从库了
- 默认情况下,MySQL将OPTIMIZE TABLE语句写入二进制日志,以便它们复制到slave服务器。如果不想写二进制日志,使用命令时加上NO_WRITE_To_BINLOG或LOCAL关键字即可。
- 使用这个语句需要具有对目标表的SELECT、INSERT权限。
-
注意:
需要有足够的空间才能进行OPTIMIZE TABLE。 (剩余空间必须 > 被 OPTIMIZE 的表的大小)
-
OPTIMIZE 只对独立表空间(innodb_file_per_table=1)才有用,对共享表空间不起作用。
对于共享表空间,如果需要瘦身: 必须将数据导出,删除ibdata1,然后将 innodb_file_per_table 设置为独立表空间, 然后将数据导入进来。
-
对于InnoDB的表,OPTIMIZE TABLE 的工作原理如下
对于InnoDB表, OPTIMIZE TABLE映射到ALTER TABLE … FORCE(或者这样翻译:在InnoDB表中等价 ALTER TABLE … FORCE),它重建表以更新索引统计信息并释放聚簇索引中未使用的空间。
当您在InnoDB表上运行时,它会显示在OPTIMIZE TABLE的输出中,如下所示: mysql> OPTIMIZE TABLE foo; +----------+----------+----------+---------------------------------------+ | Table | Op | Msg_type | Msg_text | +----------+----------+----------+---------------------------------------+ | test.foo | optimize | note | Table does not support optimize, doing recreate + analyze instead | | test.foo | optimize | status | OK | +----------+----------+----------+---------------------------------------+ # 但这个提示语可以忽略,从严格的意义讲,说InnoDB不支持optimize table,其实不太准确。 因为 MYSQL的文档说明了,当INNODB 的表,MYSQL会以 ALTER TABLE force + analyze 去执行这个命令(相当于做了recreate和analyze)。 所以最终还是会看到 OK 的状态。 # https://stackoverflow.com/questions/30635603/what-does-table-does-not-support-optimize-doing-recreate-analyze-instead-me
对于MYISAM表,OPTIMIZE TABLE 的工作原理:
1. 如果表已删除或分隔行,就修复该表。
2. 如果索引页没有排序,就排序它们。
3. 如果表的统计信息不是最新的(而且修复不能通过对索引进行排序),就更新它们。-
**执行时也可以发现报错: Temporary file write failure. **
建议参考这片文章:
Mysql optimize table 时报错 Temporary file write failure. 的解决方案
-
optimize 语句的官网介绍
如果您已经删除了表的一大部分,或者如果您已经对含有可变长度行的表(含有VARCHAR, BLOB或TEXT列的表)进行了很多更改,则应使用 OPTIMIZE TABLE。
被删除的记录被保持在链接清单中,后续的INSERT操作会重新使用旧的记录位置。您可以使用OPTIMIZE TABLE来重新利用未使用的空间,并整理数据文件的碎片。
在多数的设置中,您根本不需要运行OPTIMIZE TABLE。即使您对可变长度的行进行了大量的更新,您也不需要经常运行,每周一次或每月一次 即可,只对特定的表运行。
Mysql 5.6 之前 在OPTIMIZE TABLE运行过程中,MySQL会锁定表,5.6之后有了 Online DDL 则大大减少了锁表时间。
3. alter table、analyze table和optimize table区别
-
alter table tb_test engine = innodb;
- (也就是 recreate)MySQL 5.5以前用Offline的方式重建表,5.6以后用Online的方式重建表;
-
analyze table tb_test ;
- 重新统计表的索引信息,不会修改数据,不会重建表,整个过程加MDL读
-
optimize table tb_test ;
- 是 alter table xxx = innodb; analyze table xxx; 的過程。
4. OPTIMIZE TABLE 和ALTER TABLE xxxx ENGINE= INNODB哪個更好
- OPTIMIZE TABLE 還是ALTER TABLE xxxx ENGINE= INNODB 基本上是一樣的。但是在有些情況下,ALTER TABLE xxxx ENGINE= INNODB比較好。
- 例如: old_alter_table 系統變數沒有啟用等等。
- 另外: 對於MyISAM類型表,使用ALTER TABLE xxxx ENGINE= INNODB 是明顯要優於 OPTIMIZE TABLE這種方法的。
2.3 官方建議
MySQL官方建議不要經常(每小時或每天)進行碎片整理,一般根據實際情況,只需要每週或每月整理一次即可(我們現在是每月凌晨4點清理mysql所有實例下的表格碎片)
推薦學習:mysql影片教學
以上是MySQL怎麼解決delete大量資料後空間不釋放的問題的詳細內容。更多資訊請關注PHP中文網其他相關文章!

ACID屬性包括原子性、一致性、隔離性和持久性,是數據庫設計的基石。 1.原子性確保事務要么完全成功,要么完全失敗。 2.一致性保證數據庫在事務前後保持一致狀態。 3.隔離性確保事務之間互不干擾。 4.持久性確保事務提交後數據永久保存。

MySQL既是數據庫管理系統(DBMS),也與編程語言緊密相關。 1)作為DBMS,MySQL用於存儲、組織和檢索數據,優化索引可提高查詢性能。 2)通過SQL與編程語言結合,嵌入在如Python中,使用ORM工具如SQLAlchemy可簡化操作。 3)性能優化包括索引、查詢、緩存、分庫分錶和事務管理。

MySQL使用SQL命令管理數據。 1.基本命令包括SELECT、INSERT、UPDATE和DELETE。 2.高級用法涉及JOIN、子查詢和聚合函數。 3.常見錯誤有語法、邏輯和性能問題。 4.優化技巧包括使用索引、避免SELECT*和使用LIMIT。

MySQL是一種高效的關係型數據庫管理系統,適用於存儲和管理數據。其優勢包括高性能查詢、靈活的事務處理和豐富的數據類型。實際應用中,MySQL常用於電商平台、社交網絡和內容管理系統,但需注意性能優化、數據安全和擴展性。

SQL和MySQL的關係是標準語言與具體實現的關係。 1.SQL是用於管理和操作關係數據庫的標準語言,允許進行數據的增、刪、改、查。 2.MySQL是一個具體的數據庫管理系統,使用SQL作為其操作語言,並提供高效的數據存儲和管理。

InnoDB使用redologs和undologs確保數據一致性和可靠性。 1.redologs記錄數據頁修改,確保崩潰恢復和事務持久性。 2.undologs記錄數據原始值,支持事務回滾和MVCC。

EXPLAIN命令的關鍵指標包括type、key、rows和Extra。 1)type反映查詢的訪問類型,值越高效率越高,如const優於ALL。 2)key顯示使用的索引,NULL表示無索引。 3)rows預估掃描行數,影響查詢性能。 4)Extra提供額外信息,如Usingfilesort提示需要優化。

Usingtemporary在MySQL查詢中表示需要創建臨時表,常見於使用DISTINCT、GROUPBY或非索引列的ORDERBY。可以通過優化索引和重寫查詢避免其出現,提升查詢性能。具體來說,Usingtemporary出現在EXPLAIN輸出中時,意味著MySQL需要創建臨時表來處理查詢。這通常發生在以下情況:1)使用DISTINCT或GROUPBY時進行去重或分組;2)ORDERBY包含非索引列時進行排序;3)使用複雜的子查詢或聯接操作。優化方法包括:1)為ORDERBY和GROUPB


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

SublimeText3漢化版
中文版,非常好用

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),