记一次 Lightning 导入失败导致的 TiDB 集群重启失败事故处理

记一次Lightning导入失败导致的tidb集群重启失败事故处理

一、需求以及环境

需求:离线报表MySQL分库分表业务迁移TiDB,因为是离线报表,凌晨写入后数据不发生变化,先脚本select into outfile倒出成为多个csv文件,利用lightning快速导入到已有的低请求业务TiDB集群(已经提供线上服务)。

环境:

tidb: V4.0.9版本

lightning: V4.0.9、导入模式Local

二、问题现象

Lightning导数据,导入了几分钟后,集群不可用,取消导入,集群仍然不可用,想到重启大法好,重启集群发现集群tidb和tikv无法启动。

tikv报错日志:
[2021/01/14 19:41:55.832 +08:00] [ERROR] [sst_importer.rs:92] ["ingest failed"] [err_code=KV:SSTImporter:RocksDB] [err="RocksDB read metadata from /data/deploy/data**/import/**3b719d18-7195-4843-bb4e-00444b53faca_434317_7_4204_write.sst: Os { code: 2, kind: NotFound, message: \"**No such file or directory**\" }"] [meta="uuid: 3B719D1871954843BB4E00444B53FACA range { start: 748000000000002DFFB95F728000000000FF1400E00000000000FA end: 748000000000002DFFB95F728000000003FF3F16980000000000FA } cf_name: \"write\" **region_id: 434317 **region_epoch { conf_ver: 7 version: 4204 }"]

三、问题排查和解决

通过上面的报错日志可以发现,tikv重启在找一个/data/deploy/data/import/3b719d18-7195-4843-bb4e-00444b53faca_434317_7_4204_write.sst,从路径可以看出是import目录的一个sst文件,该文件丢失是因为我们lightning异常停止导致的丢失,并且该sst文件对应的region是434317。

我可以接受丢数据,本来import的数据就是不完整的,丢就丢了,我可以恢复后重新导入,再加上该集群有非核心业务服务在使用,我想尽快启动集群。

要想恢复集群就是从tikv中将region=434317给删除了。

尝试解决方案一:

在/data/deploy/data/import/目录touch一个空的3b719d18-7195-4843-bb4e-00444b53faca_434317_7_4204_write.sst文件,并且赋予tidb用户的权限,发现tikv还是启动不起来,报错文件内容为空。

尝试解决方案二:

之前遇到过3副本都丢失时的删除region,如下

./tikv-ctl --db /path/to/tikv/db unsafe-recover remove-fail-stores -s 4 -r 434317

thread ‘main’ panicked at ‘called Result::unwrap() on an Err value: Os { code: 2, kind: NotFound, message: “No such file or directory” }’, src/libcore/result.rs:1188:5
note: run with RUST_BACKTRACE=1 environment variable to display a backtrace.

执行报错,后来仔细看了文档才发现删除region的命令用错了,下面是unsafe-recover remove-fail-stores的使用含义。

remove-fail-stores 命令可以将故障机器的region从指定 Region 的 peer 列表中移除,此命令常用于多个 TiKV store 损坏或被删除的情况下,这些 Region 便可以使用剩下的健康副本继续提供服务。

真正的解决方案:

其实我们的目的就是将region=434317给tombstone了,以便Tikv启动时跳过对该异常region的健康检查,从而使得tikv能启动成功。在tikv节点执行下面的命令:
./tikv-ctl --db /data/deploy/data/db tombstone -r 434317 --force

tombstone 命令:在 TiKV 实例上将一些 Region 的副本设置为 Tombstone 状态,从而在重启时跳过这些 Region,避免因为这些 Region 的副本的 Raft 状态机损坏而无法启动服务。

事后处理

在导入数据之前,tidb-lightning 会自动将 TiKV 集群切换为“导入模式” (import mode),优化写入效率并停止自动压缩。若 tidb-lightning 崩溃,集群会留在“导入模式”。若忘记转回“普通模式”,集群会产生大量未压缩的文件,继而消耗 CPU 并导致延迟。此时,需要使用 tidb-lightning-ctl 手动将集群转回“普通模式“,TiDB集群才能对外提供正常服务:
bin/tidb-lightning-ctl --switch-mode=normal

最后使用tidb-backend的方式导入成功。

四、问题复盘和思考

主要还是Lightning使用问题

1、下载跟tidb版本匹配的lightning

https://download.pingcap.org/tidb-toolkit-{version}-linux-amd64.tar.gz
下载链接中的 {version} 为 TiDB Lightning 的版本号

2、采用什么导入的模式?

https://docs.pingcap.com/zh/tidb/stable/tidb-lightning-backends

  • Importer-backend:tlightning 先将 SQL 或 CSV 数据编码成键值对,由额外的组件: tikv-importer 对写入的键值对进行排序后导入 TiKV 中。

  • Local-backend:tlightning 先将数据编码成键值对并排序存储在本地临时目录(就是上文中date目录中的import子目录),然后将这些键值对以 SST 文件的形式上传到各个 TiKV 节点,然后由 TiKV 将这些 SST 文件 Ingest 到集群中。不依赖额外的 tikv-importer 组件。

  • TiDB-backend:tidb-lightning 先将数据编码成 INSERT 语句,然后通过 TiDB 执行这些 Insert SQL 语句来导入数据。

3种导入方式对比:

  • 速度:Local > importer > tidb-backend
  • 资源和网络占用:Local > importer > tidb-backend

3、导入到新集群还是已有集群?

建议导入到新集群(V4.0+),这样可以采用local这种快速的导入方式; 新集群(V4.0以下版本),可以使用import模式;如果导入到线上并且正在使用的集群,请使用tidb-backend这种后端导入模式,并且调整并发等避免影响正常的业务。

4、导入过程中的监控

建议导入过程中及时查看grafana中关于Lightning的专用监控

2赞