m6米乐安卓版下载-米乐app官网下载
暂无图片
12

mysql innodb表的碎片化和整理 -m6米乐安卓版下载

原创 kevincui 2023-12-18
615

在mysql的innodb引擎设计中,对删除一些数据的操作,只是被标记为“已删除”,而不是真正的从物理文件中删除,因而空间也没有真的被释放回收。虽然mysql中有purge线程会异步清理这些没用的数据,但是依然没有把这些空间释放出来还给操作系统重新使用。因此,数据页中存在很多空洞。当然,有新的数据插入时,会尽可能使用这些空洞的空间,进行覆盖,这样做既节省又能再次利用。

但往往不是那么尽人如意,当mysql数据库负载高,或或算法不足以满足时,会顾不上原空间利用,只会开辟新的空间。这样导致的结果是,实际数据量就只有几万行,但底层数据ibd文件会非常大。跟实际空间不成对比。这就是mysql表碎片化场景。普遍场景下对整体影响不大,但过多的碎片化会导致表扫描所花费的时间比“应该”花费的时间更长,底层io会更高。

  • 空间浪费:空间浪费不用多说,碎片占用了大量可用空间。
  • 读写性能下降:由于存在大量碎片,数据从连续规则的存储方式变为随机分散的存储方式,磁盘i0会变的繁忙,数据库读写性能就会下降。
  • 执行计划不准确导致sql语句性能下降。因为样本sample采取的页里包含空洞,导致cardinality信息不准确,执行计划选择错误。

在mysql使用经验中,容易大量碎片出现的情况如下:
1.频繁大量随机的delete操作会产生会不连续的空白空间,这些空间使用率非常底。
2.大量的update,也会产生文件碎片化,innodb的最小物理存储分配单位是页(page),而update也可能导致页分裂(page split),频繁的页分裂,页会变得稀疏,并且被不规则的填充,所以最终数据会有碎片。

mysql提供系统表和工具可以查看碎片信息。

1)命令行统计信息。

通过show status 命令查看表的情况:

mysql>show table status like 'attendance'\g; *************************** 1. row *************************** name: attendance engine: innodb version: 10 row_format: dynamic rows: 8 avg_row_length: 2048 data_length: 253040000 max_data_length: 0 index_length: 62040000 data_free: 102400 auto_increment: null create_time: 2023-09-18 18:08:38 update_time: null check_time: null collation: utf8mb4_bin checksum: null create_options: comment: 1 row in set (0.00 sec)

查询information_schema.tables获取表的碎片化信息:

mysql> select concat(table_schema, '.', table_name) as table_name, (data_length index_length) / 1024 / 1024 as total_mb, data_free / 1024 / 1024 as data_free_mb, data_free * 100/(data_length index_length) as data_free_percent, curdate() as today from information_schema.tables where table_schema not in ('mysql','sys','information_schema','performance_schema') order by data_free_percent desc limit 5; -------------------- ------------ -------------- ------------------- ------------ | table_name | total_mb | data_free_mb | data_free_percent | today | -------------------- ------------ -------------- ------------------- ------------ | book.attendance | 323.031250 | 100.000000 | 33.000 | 2023-12-18 | | book.customers | 300.031250 | 90.00000000 | 0.3000 | 2023-12-18 | | book.dataseta | 120.015625 | 4.00000000 | 0.0333 | 2023-12-18 | | book.employees | 79.0312500 | 1.00000000 | 0.0100 | 2023-12-18 | | book.jemp | 50.0468750 | 1.00000000 | 0.0100 | 2023-12-18 | | book.members | 42.0468750 | 1.00000000 | 0.0100 | 2023-12-18 | | book.opening_lines | 40.0156250 | 1.00000000 | 0.0100 | 2023-12-18 | -------------------- ------------ -------------- ------------------- ------------ 10 rows in set, 10 warnings (0.01 sec)

备注:这有可能存在不准确信息,最好在到数据目录查看文件实际大小。

2)mysql工具innochecksum分析碎片

innocchecksum是官方提供的innodb引擎文件的校验工具。该工具读取innodb表空间文件,计算每个页面的校验和,将计算出的校验和与存储的校验和进行比较。需要保证ibd文件没有文件锁,最好的方式是先关闭mysqld进程。

显示各种页类型的计数:

shell> innochecksum --page-type-summary  ./attendance.ibd 
file::./attendance.ibd
================page type summary==============
#page_count	page_type
===============================================
     625	index page         #索引页
       1	sdi index page     #数据字典也
       0	undo log page      #undo页
       1	inode page         #索引页
       0	insert buffer free list page #插入缓冲空闲列表页
     523	freshly allocated page       #表示还没有使用的页
       1	insert buffer bitmap         #插入缓冲位图页
       0	system page                  #系统页 
       0	transaction system page      #事务数据页
       1	file space header            #文件空间标头
       0	extent descriptor page      
       0	blob page                    #blob数据页
       0	compressed blob page         #压缩的blob页
       0	subsequent compressed blob page
       0	sdi blob page                #sdi blob页
       0	compressed sdi blob page     #压缩的 sdi  blob页
       0	other type of page           #其他页
===============================================
additional information:
undo page type: 0 insert, 0 update, 0 other
undo page state: 0 active, 0 cached, 0 to_free, 0 to_purge, 0 prepared, 0 other

备注:需要关注freshly allocated page:可用页

显示表空间中每个页的分布情况:

shell> innochecksum --page-type-dump=/tmp/a.txt  ./attendance.ibd 
shell> cat /tmp/a.txt 

image.png
备注:这里的index page都是按照page num的顺序从小到大排列的。records显示每个page的行数。
garbage已经被删除的记录行数。从这里看出是否复用了这个页。

在mysql碎片整理,有如下3种技术方式:

  • alter table tbl_name engine=innodb
    当指定engine子句时,alter table会重新构建该表。在现有的innodb表上运行alter table tbl_name engine=innodb将执行“null”alter table操作,该操作可用于对innodb表进行碎片整理。
  • optimize table回收未使用的空间并对数据文件进行碎片整理。在对表进行大量更改后,此语句还可以提高使用该表的语句的性能,有时甚至可以显著提高性能。
  • 另一种方法是逻辑导出导入,删除原表,然后从新加载数据。可以使用mysqldump方式。
    alter操作和optimize会锁表,属于高危命令,时间长短依据数据量的大小。

按照上诉技术手段,可以在主从节点上轮回切换,进行碎片整理。注意,避免在业务高峰期进行,以减少对系统性能的影响。

对于mysql碎片情况,官方建议不要经常进行碎片整理,一般根据实际情况,当出现碎片,并导致的性能问题比较严重时,选择合适的时机和合适的方式进行整理。

对于日常碎片化监控,建议先通过系统表统计信息进行监控。当碎片情况比较严重时,使用innochecksum进行二次分析,之后进行碎片整理。

最后修改时间:2023-12-19 10:07:53
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【米乐app官网下载的版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论

网站地图