无语了,直到今天,我才揪出MySQL磁盘消耗迅猛的“真凶”( 二 )


首先我们需要了解到使用bulk-delete时,sql是如下执行的:
mysql> delete from tablename_v2 where id >xxx and id < xxx limit 10000.如果您之前关注过笔者的文章,应该知道,当使用了delete from xxx where xxx limit 语法时,会将binlog_format从mixed转为row,这样的话,删除的同时,binlog由于转为了row格式也在激增,这与我们的预期是不符的 。
因此最终的命令为:
pt-archiver --sourceh=c3-helei-db01.bj,D=helei,t=tablename_v2,u=sys_admin,p=MANAGER--where 'id<2577754125' --purge --progress 10000 --limit=10000--no-check-charset --txn-size=10000  --statistics --max-lag=20--check-slave-lag c3-helei-db02.bj去掉了bulk-delete,这样的话就能够保证正常的delete,而不加limit,binlog不会转为row格式导致磁盘消耗继续激增 。
对于Innodb引擎来说,delete操作并不会立即释放磁盘空间,新的数据会优先填满delete操作后的“空洞”,因此从监控来看就是磁盘不会进一步消耗了,说明我们的pt-archiver工具删除是有效的 。
Part4:困惑
首先我们要知道,当你面对一张数据量庞大的表的时候,有些东西就会受限制,例如:

  1. 不能alter操作,因为这会阻塞dml操作 。
  2. 对于本案例,空间本就不足,也不能使用pt-online工具来完成 。
对于不能alter其实是比较要命的,比如开发要求在某个时间段尽快上线新业务,而新业务需要新增列,此时面对这么庞大的量级,alter操作会异常缓慢 。
因此,笔者与研发沟通,尽快采用物理分表的方式解决这个问题,使用物理分表,清理表的操作就会很容易,无需delete,直接drop 老表就可以了 。其次,物理分表让alter语句不会卡住太久,使用pt-online工具也不会一次性占据过多的磁盘空间诱发磁盘空间不足的告警 。
再有就是迁移TiDB,TiDB相较MySQL更适合存储这类业务 。
Part5:再谈binlog_format
我们选取其中高峰期的binlog发现其update操作转为了row格式,记录了所有列变更前后的所有信息,而binlog中并未出现update xxx limit这种操作,那又会是什么引发的row格式记录呢?
这里这篇文章又抛出一个新的案例,在官网那篇何时mixed转row格式中又一个没有记录的情况
官方文档:
When running in MIXED logging format, the server automatically switches from statement-based to row-based logging under the following conditions:When a DML statement updates an NDBCLUSTER table.When a function contains UUID().When one or more tables with AUTO_INCREMENT columns are updated and a trigger or stored function is invoked. Like all other unsafe statements, this generates a warning if binlog_format = STATEMENT.When any INSERT DELAYED is executed.When a call to a UDF is involved.If a statement is logged by row and the session that executed the statement has any temporary tables, logging by row is used for all subsequent statements (except for those accessing temporary tables) until all temporary tables in use by that session are dropped.This is true whether or not any temporary tables are actually logged.Temporary tables cannot be logged using row-based format; thus, once row-based logging is used, all subsequent statements using that table are unsafe. The server Approximates this condition by treating all statements executed during the session as unsafe until the session no longer holds any temporary tables.When FOUND_ROWS() or ROW_COUNT() is used. (Bug #12092, Bug #30244)When USER(), CURRENT_USER(), or CURRENT_USER is used. (Bug #28086)When a statement refers to one or more system variables. (Bug #31168)我们这个案例中又出现了一个新的因素就是:
当表结构中存在多个唯一索引(包括主键id),本案例中存在主键和UNIQUE KEY `uk_mailNo`这个唯一索引,且使用了


推荐阅读