故障分析
作者:林靖华,开源数据库技术爱好者,擅长 MySQL 和 Redis 的运维。
爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。
本文约 1200 字,预计阅读需要 4 分钟。
磁盘空间告警 是 DBA 在数据库运维过程中经常遇到的一种情况。在近期的一次巡检就发生了一次,借此机会介绍一下如何使用 pt-osc[1](pt-online-schema-change)工具快速清理数据。
在清理数据之前,一定要联系业务,沟通了解情况后,再开始进行清理工作。
2决策
沟通后得知,库内有一张大表是只需要保留特定条件数据,且这部分数据可能占总量的 10% 甚至更少。
能否直接删除不需要的数据呢?
一般情况下,一次性删除大量数据会导致大事务,从而影响主从复制。因此,部分运维人员会选择使用 pt-archiver[2] 或其他工具分批次删除少量数据。尽管这种方法能够达到目的,但在数据量较大的情况下,执行时间较长,并且会产生大量 binlog,显然并非最优解决方案。
能否换一种思路实现?
在本案例中,我们可以把关注点放在需要保留的数据上,因为这部分数据占比很低。如果先将需要保留的数据导入到临时表中,完成后再切换两张表,旧的数据可以直接通过 DROP 表的方式来清理,这种方式不仅快速,而且不会生成大量 binlog,处理效率应该更高。尽管该方法可行,但需要暂停业务,因为数据是不断在写入的,新增的数据没法实时同步到临时表中。
为什么选择使用 pt-osc?
我们通过观察可以发现,其实上面方法的执行逻辑与 pt-osc 的 Online DDL 原理类似,都是迁移数据然后切换表,但是它帮忙处理了中间新写入数据的同步,所以动手能力强的人实际上可以根据其逻辑自行编写工具。不过现在也可以使用新版本的 pt-osc 来实现这个效果。
percona-toolkit v3.6.0 版本对 pt-osc 新增参数
--where,只复制满足条件的数据,利用这个参数即可实现数据的过滤。
3实操
先准备一个表(数据记录时间范围:2025-02-01 - 2025-02-01)。
代码语言:javascript代码运行次数:0运行复制mysql> select time,count(*) from test group by time;
+---------------------+----------+
| time | count(*) |
+---------------------+----------+
| 2025-02-01 00:00:00 | 10000 |
| 2025-02-02 00:00:00 | 10000 |
| 2025-02-03 00:00:00 | 10000 |
| 2025-02-04 00:00:00 | 10000 |
| 2025-02-05 00:00:00 | 10000 |
| 2025-02-06 00:00:00 | 10000 |
| 2025-02-07 00:00:00 | 10000 |
| 2025-02-08 00:00:00 | 10000 |
| 2025-02-09 00:00:00 | 10000 |
| 2025-02-10 00:00:00 | 10000 |
| 2025-02-11 00:00:00 | 10000 |
| 2025-02-12 00:00:00 | 10000 |
+---------------------+----------+
假设我们仅需保留 2025-02-12 的数据,则可指定 --where 'time>="2025-02-12"' (当使用 --where 参数时,若未同时指定 --no-drop-new-table 和 --no-swap-tables,则必须指定 --force 才能继续操作),执行的 DDL 操作只需设置为 engine=innodb 即可。
[root@192-168-13-131 bin]# ./pt-online-schema-change -u root -p 123456 -h 10.186.60.84 -P 3306 --execute --force --where 'time>="2025-02-12"' --alter 'engine=innodb' D=kk,t=test
Found 1 slaves:
10-186-60-87 -> 10.186.60.87:3306
Will check slave lag on:
10-186-60-87 -> 10.186.60.87:3306
Operation, tries, wait:
analyze_table, 10, 1
copy_rows, 10, 0.25
create_triggers, 10, 1
drop_triggers, 10, 1
swap_tables, 10, 1
update_foreign_keys, 10, 1
Altering `kk`.`test`...
Creating new table...
Created new table kk._test_new OK.
Altering new table...
Altered `kk`.`_test_new` OK.
2025-02-13T14:47:50 Creating triggers...
2025-02-13T14:47:51 Created triggers OK.
2025-02-13T14:47:51 Copying approximately 109467 rows...
2025-02-13T14:48:02 Copied rows OK.
2025-02-13T14:48:02 Analyzing new table...
2025-02-13T14:48:02 Swapping tables...
2025-02-13T14:48:03 Swapped original and new tables OK.
2025-02-13T14:48:03 Dropping old table...
2025-02-13T14:48:03 Dropped old table `kk`.`_test_old` OK.
2025-02-13T14:48:03 Dropping triggers...
2025-02-13T14:48:03 Dropped triggers OK.
Successfully altered `kk`.`test`.
最终表中仅保留 2025-02-12 的数据。若需保留原始数据,可使用 --no-drop-old-table 参数。
mysql> select time,count(*) from test group by time;
+---------------------+----------+
| time | count(*) |
+---------------------+----------+
| 2025-02-12 00:00:00 | 10000 |
+---------------------+----------+
需要注意的是,由于 pt-osc 会创建触发器以同步增量数据,而当前并未对这部分数据进行过滤,因此,若 --where 条件之外的数据在此期间发生写入或更新操作,同样会被同步至新表中,可根据个人需要选择保留或者删除这部分数据。
参考资料
[1]
pt-osc: .html
[2]
pt-archiver: .html
本文关键字:#MySQL# #pt-osc# #磁盘清理#
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。原始发表:2025-02-18,如有侵权请联系 cloudcommunity@tencent 删除数据库运维工具数据同步

发布评论