首页 > 其他分享 >使用tidb-toolkit批量删除/更新数据

使用tidb-toolkit批量删除/更新数据

时间:2023-08-23 12:38:26浏览次数:38  
标签:批量 chunk time dml toolkit tk rowid tidb

作者: realcp1018



一、背景简介

在日常使用TiDB的场景中经常会遇到此类问题:

  1. 建表时未使用分区表,导致数据删除困难。
  2. 想要快速的批量更新数据,但是每次都需要编写繁杂的跑批任务。
  3. 想要在数亿、数十亿的大表中删除几千完或几百万数据但是却总是遇到“事务大小超出限制”的错误。

为解决此类问题我编写了一个通用的删除工具,用于处理此类“事务大小超出限制”的错误。 可类比mysql的oak-chunk-update工具。 这个工具在我司生产环境运行两年以来,高效的删除了大量数据,目前已趋于完善,因此写笔记分享出来。

项目地址:https://github.com/realcp1018/tidb-toolkit



二、环境要求

git clone https://github.com/realcp1018/tidb-toolkit.git

运行 "python3 -m pip install -r requirements.txt" 安装python3库依赖.

将项目目录添加至$PYTHONPATH:

# 假设项目被clone至/data目录下:  
export PYTHONPATH=$PYTHONPATH:/data/tidb-toolkit



三、使用示例

1. 使用tk_dml_byid对表执行 "delete from where ..." (表必须未设置auto_random或shard_rowid_bits,如果误在此类表上运行也关系,只是效率极底)

# 编辑 tidb.toml 的 [basic], [dml] 和 [dml.by_id] 部分,其他部分的设置不影响本次运行  
db = "test"  
table = "tb1kb_1"  
sql = "delete from tb1kb_1 where is_active=0;"  
execute = false  
# 运行:  
python3 scripts/tk_dml_byid.py -f conf/tidb.toml -l tb1kb_1.log  
# execute = false: 设置此项表示不实际进行数据删除,仅打印一个拆分后的示例SQL,适用于比较谨慎的场景  
# 确保输出的拆分SQL符合预期,然后可以修改为true实际运行

2. 使用tk_dml_by_time对表执行 "delete from where ..." (表已设置auto_random或shard_rowid_bits,或者仅仅想根据时间列删除极少部分数据)

# 编辑 tidb.toml 的 [basic], [dml] and [dml.by_time] 部分  
db = "test"  
table = "tb1kb_1"  
sql = "delete from tb1kb_1 where is_active=0;"  
# 假设 create_time 类型为 int(时间精度为ms)  
split_column = "create_time"  
split_column_precision = 3  
split_interval = 3600  
start_time = "2021-01-01 00:00:00"  
end_time = "2021-12-31 00:00:00"  
execute = false  
# 运行:  
python3 scripts/tk_dml_by_time.py -f conf/tidb.toml -l tb1kb_1.log

3. 使用tk_chunk_update对表执行 "delete from where ..." (可覆盖上述两种场景,无需考虑表是否设置auto_random或shard_rowid_bits)

# 编辑 tidb.toml 的 [basic], [dml] 和 [dml.chunk_update] 部分  
db = "test"  
table = "tb1kb_1"  
sql = "delete from tb1kb_1 where is_active=0;"  
execute = false  
# 运行:  
python3 scripts/tk_chunk_update.py -f conf/tidb.toml -l tb1kb_1.log  
# execute = false  
# 确保输出的拆分SQL符合预期,然后可以修改为true实际运行



四、常见问题

1. 支持哪些类型的SQL?

工具支持以下几种SQL类型:

1.delete from <table> where <...>  
2.update <table> set <...> where <...>  
3.insert into <target_table> select <...> from <source_table> where <...>

非DML类型会直接报错退出。

2. 如何在tk_chunk_update 和 tk_dml_by_id, tk_dml_by_time之间做出选择?

tk_chunk_update无需人为进行表的类型判断,适用性高,只要是tidb的表都可以使用。 相比tk_dml_by_id可以避免大量无效rowid扫描,相比tk_dml_by_time则单条SQL执行更快。

但tk_chunk_update有极底概率遇到性能衰退的情况:如果表包含大量空region(或gc缓慢),那么在执行日志中你会看到如下记录:

ConnectionPool Monitor: Size 99以及:chunk xxx Done [split_time=0:00:00.523525] [duration=0:00:00.229860] [rows=1000] [sql=...]

可以看到 split_time 大于 duration,这意味着chunk的生产速度慢于消费速度, 而tk_chunk_update的要点之一是就是需要保证chunk的生产速度远大于消费速度。

其原理如下, 首先ChunkSpliter.split()通过如下查询条件获取chunk的右边界:

select max(rowid) from   
   (select rowid from table_name where rowid > current_rowid order by rowid limit 0,chunk_size) t

并以current_rowid作为chunk左边界,然后生成拆分后的SQL,输出一个Chunk同时将current_rowid推进至chunk右边界以便下一个chunk拆分使用,而split()是一个python生成器。

然后Executor遍历split()生成的chunk,调用其execute方法并将其作为一个future放入ThreadPoolExecutor中(执行并发度为max_workers)。

这个机制要求chunk的生成速度大于消费速度,否则会衰退为单线程执行,但是为目前了规避by_id的缺点又必须采用这种动态生成的方式,因此当你遇到此类性能衰退时, 请使用 tk_dml_by_id/tk_dml_by_time.

3. 关于 tk_dml_byid.py 和 tk_dml_bytime.py的拆分方式

By id:

  • 默认使用rowid作为拆分列(如官网所示,数字类型主键就是rowid,其他情况则有一个内置的_tidb_rowid作为rowid)
  • 如果表设置了(SHARD_ROW_ID_BITS 或 auto_random), 那么建议使用 tk_dml_bytime 或 tk_chunk_update.
  • SQL的拆分方式很简单,直接按rowid累加batch_size拆分为无数个batch(例如rowid >= 1 and rowid < 1000), 并发执行度为 <max_workers>.

By time:

  • 与by id的拆分方式相似,但是是通过时间列拆分为无数个task,拆分单位为配置文件中的 split_interval
  • 执行方式与by id略有不同,因为按时间列拆分后的task内部可能包含的记录数扔超出事务限制,因此实际上在task内部会以batch_size为单位顺序执行同一条分页SQL直到影响行数为0
  • 通过 grep Finished <log-name> | tail 可以看到有多少task已完成

3. 关于 tk_chunk_update.py 的执行进度查看

通过如下命令可以查看当前任务的执行进度:

tailf <log-file>|grep "write savepoint"

4. 关于 savepoint 和失败重试

tk_dml_by_id.py 和 tk_chunk_update.py 在执行过程中会生产检查点(如未设置savepoint配置则会生成一个默认的检查点文件),检查点表示在这之前已经处理完毕的rowid。 无论是异常退出还是主动终止,再次运行时如果检查点文件存在则会跳过已处理的rowid.tk_dml_by_time.py 则 不会 产生检查点,如果任务失败建议查看执行日志手动设置一个start_time然后重跑,通常来说只需要选一个相对较早的时间即可。

标签:批量,chunk,time,dml,toolkit,tk,rowid,tidb
From: https://blog.51cto.com/u_15550868/7201149

相关文章

  • 简单理解 TiDB Serverless branching
    作者:shiyuhang0TiDBServerless作为TiDB的云上产品。提供了一种完全托管的、自动扩缩容的TiDB部署方式,可以让用户无需关心底层节点,即可快速使用TiDB数据库,并根据应用负载自动扩缩容。TiDBServerless在2023.07.10正式GA,同时带来了TiDBServerlessbranching.什么是......
  • Oracle-TiDB迁移-生僻字乱码问题
    作者:longzhuquan背景某去O场景业务上线测试,再执行某张表缩字段时报错。现象执行缩字段语句ALTERTABLEschemaname.tablenameMODIFYCOLUMNlicensenovarchar(50)CHARACTERSETutf8mb4COLLATEutf8mb4_binNULLCOMMENT'发动机号';报错信息"incorrectstringvalu......
  • TiDB 源码编译之 TiFlash 篇
    作者:ShawnYan导言TiFlash从去年四月一日开源至今已经过去将近一年半,这段时间里TiFlash从v6.0.0-DMR升级到了v7.3.0-DMR,并增加了若干新特性,比如支持MPP实现窗口函数框架,新增支持若干算子和函数下推,支持AWSS3算存分离等。先来回顾一下TiFlash资源精华帖,【重磅消息】......
  • 基于 Vercel & TiDB Serverless 的 chatbot
    作者:shiyuhang0#前言TiDBServerless去年就有和Vercel的集成了,同时还有一个bookstoretemplate方便大家体验。但个人感觉bookstore不够炫酷,借2023TiDBhackthon的机会,我搞了个maskchatbot,你可以在maskchatbot上选定角色,基于此生成prompt来更好的使用ChatGPT......
  • 我和 TiDB 的故事 | 远近高低各不同
    作者:ShawnYanHi,TiDB,Again!书接上回,《我和TiDB的故事|横看成岭侧成峰》,一年时光如白驹过隙,这一年我好似在TiDB上投入的时间总量不是很多,但是断断续续也一直有在关注使用。当然,数据是造不了假的,看热力图就知道我一直都在,只是每逢周末就忘记登录,所以直到现在也还没达到......
  • TiDB 多集群告警监控-中章-融合多集群 Grafana
    作者:longzhuquan背景随着公司XC改造步伐的前进,越来越多的业务选择TiDB,由于各个业务之间需要物理隔离,避免不了的TiDB集群数量越来越多。虽然每套TiDB集群均有两个详细的监控Dashboard、Grafana,但对于运维来说几十套集群的监控、告警、巡检均需消耗巨大的精力。上篇介绍了......
  • 云原生批量计算引擎 Volcano社区v1.8.0版本正式发布
    本文分享自华为云社区《云原生批量计算引擎Volcano社区v1.8.0版本正式发布》,作者:云容器大未来。北京时间2023年8月17日,Volcano社区v1.8.0版本正式发布,此次版本增加了以下新特性:支持vGPU调度及隔离支持vGPU和用户自定义资源的抢占能力新增JobFlow工作流编排引擎......
  • 2023-08-22 SAS数据集与Excel文件之间的批量转换 Batch File Exchange between SAS an
    参考资料:BatchFileExchangebetweenSASandExcel-theMagicofCallExecute我们经常需要在SAS和MSExcel之间传输数据。默认情况下,SASlibnameengine或PROCIMPORT/EXPORT只能在SAS和Excel之间传输单个文件。在多个文件的情况下,一个一个地传输文件会显得过于繁......
  • tidb快照备份并发送企业微信机器人通知
    tidb备份使用的是br进行快照备份+日志备份具体代码如下#qiyewx.pyimportjsonfromdatetimeimportdatetimeimportrequestsfromconfigimport*#可以把机器人的配置信息写到一个单独的config里面也可以直接填到脚本里classQiyewx():def__init__(self):......
  • Shopify 内容玩法之 Discounts 折扣码批量上传:matrixify
     折扣码使用的插件是:Matrixify。这个插件可以批量上传Products,Discounts等数据,可以直接使用excel模板创建数据。Discounts的excel模板,见下表:需要注意的几点:Code和Title保持一致,方便在Discounts列表查看当前折扣码的名称DiscountsValue是减掉的金额您需......