首页 > 数据库 >optimize table 治理mysql 高水位和空间碎片

optimize table 治理mysql 高水位和空间碎片

时间:2023-07-10 23:01:00浏览次数:40  
标签:task batch detail swltest mysql table optimize

问题背景

随着系统上线时间的增长, mysql数据库的数据目录的文件系统使用率已经快要耗尽。从最初的两三个月 truancate一次 日志表,到最后每周要truancate 多次日志表。
业务侧将数据库中历史数据(超过全部数据的2/3)逐渐进行了迁移(采用目标库insert, 源库delete的方式),这些表中有多个超过100GB的大表, 甚至有两个在500GB以上的超大表。
虽然数据被迁移了,但是空间并没有被释放出来,业务侧的事情完成了,接下来需要我们在释放这些delete之后留下的空间。

注意事项

  • 锁表

引用在操作的准备阶段和提交阶段,会对表加排它锁。特别是准备阶段, 如果表上有大事务, 那 optimize操作在拿到锁之前会阻塞 后续的所有操作,包括select

  • 磁盘空间

引用执行过程中,会复制表的数据到一个中间文件中。所以需要注意有没有足够的空间进行此操作
执行过程中, 表上的DML 操作会记录到一个临时文件中, 文件的大小受innodb_online_alter_log_max_size控制,单位是字节。 如果表上的dml比较多, 执行操作前要调大 innodb_online_alter_log_max_size 参数。(此参数动态生效)

  • 主从延时

optimize table 是一个比较耗时的操作,当操作被同步到从库之后,就会造成主从延时。对于对延时敏感的系统,建议在主库执行时加入NO_WRITE_TO_BINLOG选项,不将此操作记入binlog

查询表碎片率

使用下面的SQL 可以查询表的锁片率,数据来源于统计信息, 不是非常准确,仅供参考

select 
   table_name,engine,
   table_rows,
   round((data_length+index_length+DATA_FREE)/1024/1024/1024,2 ) size_GB,
   round(DATA_FREE/1024/1024/1024,2) free_GB 
 from information_schema.tables where table_schema='xxx' 
order by data_free;

执行过程

OPTIMIZE NO_WRITE_TO_BINLOG TABLE table_name;

NO_WRITE_TO_BINLOG 使此操作不计入binlog, 也就不会同步到从库。这样可以避免 此语句同步到从库之后,造成主从延时。主库执行完之后,再到从库执行同样的语句。

执行开始后,需要注意一下mysql会话执行情况;
使用如下sql查询,如果 会话处在altering table 状态,则说明已经开始执行, 这个阶段不会再锁表,可以正常进行dml和select操作。

select id, host, user, db, state, info, time from information_schema.processlist  
where info like "optimize%"\G

optimize table 治理mysql 高水位和空间碎片_表碎片

如果有会话会话处在 waiting lock 阶段,则说明 OPTIMIZE 被大事务阻塞。建议立刻停止此操作,杀掉大事务或换个时间再执行

select id, host, user, db, state, info, time from information_schema.processlist  
where info like "%batch_task_detail%"\G

optimize table 治理mysql 高水位和空间碎片_表碎片_02

执行结果

正常执行完之后会有如下提示信息

(root@localhost) [swltest:8801]> optimize table batch_task_detail;
+---------------------------+----------+----------+-------------------------------------------------------------------+
| Table                     | Op       | Msg_type | Msg_text                                                          |
+---------------------------+----------+----------+-------------------------------------------------------------------+
| swltest.batch_task_detail | optimize | note     | Table does not support optimize, doing recreate + analyze instead |
| swltest.batch_task_detail | optimize | status   | OK                                                                |
+---------------------------+----------+----------+-------------------------------------------------------------------+
2 rows in set (13 min 41.83 sec)

如果执行失败, 也会有失败的提示信息, 比如:

(root@localhost) [swltest:8801]> optimize table batch_task_detail;
+---------------------------+----------+----------+--------------------------------------------------------------------------------------------------------------------------------------+
| Table                     | Op       | Msg_type | Msg_text                                                                                                                             |
+---------------------------+----------+----------+--------------------------------------------------------------------------------------------------------------------------------------+
| swltest.batch_task_detail | optimize | note     | Table does not support optimize, doing recreate + analyze instead                                                                    |
| swltest.batch_task_detail | optimize | error    | Creating index 'FTS_DOC_ID_INDEX' required more than 'innodb_online_alter_log_max_size' bytes of modification log. Please try again. |
| swltest.batch_task_detail | optimize | status   | Operation failed                                                                                                                     |
+---------------------------+----------+----------+--------------------------------------------------------------------------------------------------------------------------------------+

时间参考

机械盘中, 55G大的表执行完成大概需要 13分钟。

标签:task,batch,detail,swltest,mysql,table,optimize
From: https://blog.51cto.com/u_13482808/6681890

相关文章

  • MySQL SQL限制参数
    经常了解到MySQL使用过程中,因为这个那个SQL语句导致系统负载高,变慢等问题。可以说数据库性能问题90%以上是不良SQL引起的。前期发现不了,一旦压力负载上来,问题就爆发。应对这种情况,规定了开发规范,并且起到了很大的限制作用,但由于疏忽或大意,往往会存在漏网之鱼;对于这样的情况MySQL也......
  • mysql中innodb的索引结构以及使用B+树实现索引的原因?
    在MySQL中,InnoDB引擎使用B+树数据结构来实现索引。B+树是一种平衡的多叉树,它具有以下优点:有序性:B+树的叶子节点是按照键值大小顺序存储的,这样可以方便地进行范围查询操作,提高查询效率。平衡性:B+树通过自动调整节点的分裂和合并来保持树的平衡,使得所有叶子节点到根节点的路径长度相......
  • python: sqlalchemy ORM in mysql
     """StudengMaping.pyORM(ObjectRelationalMapping)学生表实体类对象关系映射one-oneone-moremore-onemore-moredate2023-06-23edit:GeovinDu,geovindu,涂聚文ide:PyCharm2023.1python11sqlalchemy2.0.1.6https://docs.sqlalchemy.org/en/20/cor......
  • 2.mysql的索引
    一、索引概述索引是表的目录,在查找内容之前可以先在目录中查找索引位置,以此快速定位查询数据。对于索引,会保存在额外的文件中。索引是帮助MySQL高效获取数据的排好序的数据结构。平时代码中为了方便查询,我们使用的哈希表、链表、二叉树等数据结构存储相关数据,使用二分、二叉搜......
  • python之数据库MySQL
    数据的演变史#以ATM为例#1.把数据存放在单个文件里面 1.文件名不规范2.数据格式也不规范 kevin|123kevin$123kevin*123#2.软件目录开发规范 db文件夹里 #当数据量多的时候,会产生很多的文件,多次读取文件会占用大量的资源#3.数据库阶段 把数据......
  • MYSQL--数据取整的方法
    在MySQL中,我们经常会需要取整数。本篇文章将详细介绍MySQL中取整数的多种方法。一、使用ROUND函数ROUND函数用于将一个数四舍五入到指定的小数位数。如果小数位数为0,则返回整数部分。 为小数位数。SELECTROUND(3.14159,0);--结果为3SELECTROUND(3.14159,1);--结果为......
  • sql记录:FIELD函数解决mysql中in传值顺序问题
    1.问题描述in查询的结果传值顺序与结果显示顺序不一致,默认对id进行排序显示结果,eg:如果是5号用户先点赞,1号用户后点赞,但是查询结果是1号用户显示在5号用户的前面,也就是说导致结果1号用户先点赞,5号用户后点赞,需要使用FIELD函数解决2.问题解决SELECTid,phone,password,nick_n......
  • 数据库mysql
    数据的演变史'''以ATM为例'''1.把数据存在了文件中文件名:user.txt、userinfo.txt数据格式:kevin|123、kevin@123、kevin!1232.软件开发目录规范db文件夹#专门用来存储数据文件,但是,当数据文件较多的时候,占用过多的资源,也会产生很多的文件......
  • 碎片对MySQL的影响
    常见的碎片类型·SegmentFragmentation:段产生了碎片;没有按照数据的顺序存储,或者在数据页之间有空的页·TablespaceFragmentation:表空间中存储的是非连续的文件系统块·TableFragmentation:表中数据不是按照主键的顺序存储的。或者表的页有大量空闲空间。比如,表定义成了堆......
  • MySQL5.6.x二进制包升级到5.7.x
    #!/bin/bash#mysql数据库用户名myuser="root"#mysql数据库密码mypwd="123456"#数据库备份路径dbbakdir="/data/dbbak"#数据库目录datadir="/data/mysql"#系统mysql用户sysmysqluser="mysql"#系统mysql组sysmysqlgroup="mysql"#my......