相信很多 DBA 同学都碰到过这个问题:用一条 DML SQL 语句执行大批量数据更新或删除操作时(例如:定期删除过期的数据或清理无效的数据记录),如果不具备适当的索引,一旦单条 SQL 影响的行数过多,正常业务的写入操作被阻塞,可能引起业务波动,严重时可能导致业务不可用。
执行大批量数据变更操作
而正常情况下又不会因为这样的一次性操作去建立索引,为了避免对系统性能造成过大影响,我们通常采用存储过程或编写临时代码等方式,以分批处理这些庞大的数据集。
然而,由于单个的存储过程或代码只能对应一个需求,无法复用于其他新需求,因此,每次都需要临时修改或编写,同时还可能引入不确定性风险,所以在应对不同类型的数据更新需求时,我们需要更具弹性以及通用的方法。
介绍一下我们今天的备选方案,即通过“无锁”的方式实现数据变更,以允许其他并发的 DML,提升系统的并发性能。由于无锁结构变更叫 OnlineDDL,那我们姑且把它叫做 OnlineDML。
避免数据表阻塞,保障业务正常运行
既然目的是防止一个大事务的 DML 操作导致的表阻塞,那么 OnlineDML 的核心需求就是将该大 DML 拆分成多个小批量变更的 DML 分批执行,确保在线业务的正常访问不受影响。这一点对于在线系统,尤其是在紧急情况下,是一项至关重要的保障。
说说笔者公司的大批量 DML 变更场景,我们需要清理订单表中 3 年前的历史数据,这个变更涉及千万行级别的删除操作,只用一条 DML 的情况下会对业务库造成较大影响,因此需要用到 NineData 的 OnlineDML 功能来实现无锁数据变更。
由于操作非常简单,他们也有较为详细的文档,我大致列一个操作流程:
我做的
1.为目标需要进行大批量 DML 变更的数据源开启 OnlineDML 功能。
开启 OnlineDML 功能
2.通过 NineData 的 SQL 任务功能对数据源发起变更申请。
数据源发起变更
数据源发起变更审批
提示
这个工具有一个定时执行的功能,相当惊喜,可省了我不少事,把时间定在业务低峰期的半夜 3 点,晚上不用熬夜了。
定时执行
NineData 做的:
其实只要做这两个操作就完事了,剩下的就交给 NineData 搞定,大体上它会帮我做如下一系列的动作:
- 检测该 DML 语句需要扫描的数据行数。
- 发现扫描的数据行数超过预设的阈值,为该 DML 语句进行适当的拆分。
- 分批执行拆分后的 DML 语句,每个批次的变更行数基于我预先配置的值。
- 执行过程中同步分析数据库的压力,当检测到数据库压力过大,自动等待一段时间,以保障数据库性能。
体验感受
一番操作下来,首先感受到的是 NineData OnlineDML 的界面简单明了。在 NineData 控制台中,通过几个简单的步骤配置 OnlineDML 相关规则,从设置 DML 语句扫描行数阈值到开启 OnlineDML 功能,再到配置分批大小和等待时间,一切都很丝滑。
而最重要的是使用效果,在清理将近 1000 万行数据的过程中,业务库没有任何明显的波动,毫无疑问,NineData OnlineDML 方案不费吹灰之力解决了大批量数据变更的痛点问题,为各类在线系统提供了更为灵活和通用的解决方案。
总结
本次通过 NineData OnlineDML 功能为笔者轻松解决了清理千万行级别过期数据时的业务表锁定问题,下次分享一个让业务库自动实现周期性数据归档,以及数据清理的方法,敬请期待。