迁移常见问题

本文介绍 TiDB 数据迁移中的常见问题。

如果要查看迁移相关工具的常见问题,请参考以下链接:

全量数据导出导入

如何将一个运行在 MySQL 上的应用迁移到 TiDB 上?

TiDB 支持绝大多数 MySQL 语法,一般不需要修改代码。

导入导出速度慢,各组件日志中出现大量重试、EOF 错误并且没有其他错误

在没有其他逻辑出错的情况下,重试、EOF 可能是由网络问题引起的,建议首先使用相关工具排查网络连通状况。以下示例使用 iperf 进行排查:

  • 在出现重试、EOF 错误的服务器端节点执行以下命令:

    1. iperf3 -s
  • 在出现重试、EOF 错误的客户端节点执行以下命令:

    1. iperf3 -c <server-IP>

下面是一个网络连接良好的客户端节点的输出:

  1. $ iperf3 -c 192.168.196.58
  2. Connecting to host 192.168.196.58, port 5201
  3. [ 5] local 192.168.196.150 port 55397 connected to 192.168.196.58 port 5201
  4. [ ID] Interval Transfer Bitrate
  5. [ 5] 0.00-1.00 sec 18.0 MBytes 150 Mbits/sec
  6. [ 5] 1.00-2.00 sec 20.8 MBytes 175 Mbits/sec
  7. [ 5] 2.00-3.00 sec 18.2 MBytes 153 Mbits/sec
  8. [ 5] 3.00-4.00 sec 22.5 MBytes 188 Mbits/sec
  9. [ 5] 4.00-5.00 sec 22.4 MBytes 188 Mbits/sec
  10. [ 5] 5.00-6.00 sec 22.8 MBytes 191 Mbits/sec
  11. [ 5] 6.00-7.00 sec 20.8 MBytes 174 Mbits/sec
  12. [ 5] 7.00-8.00 sec 20.1 MBytes 168 Mbits/sec
  13. [ 5] 8.00-9.00 sec 20.8 MBytes 175 Mbits/sec
  14. [ 5] 9.00-10.00 sec 21.8 MBytes 183 Mbits/sec
  15. - - - - - - - - - - - - - - - - - - - - - - - - -
  16. [ ID] Interval Transfer Bitrate
  17. [ 5] 0.00-10.00 sec 208 MBytes 175 Mbits/sec sender
  18. [ 5] 0.00-10.00 sec 208 MBytes 174 Mbits/sec receiver
  19. iperf Done.

如果输出显示网络带宽较低、带宽波动大,各组件日志中就可能出现大量重试、EOF 错误。此时你需要咨询网络服务供应商以提升网络质量。

如果输出的各指标良好,请尝试更新各组件版本。如果更新后仍无法解决问题,请移步 AskTUG 论坛寻求帮助。

不小心把 MySQL 的 user 表导入到 TiDB 了,或者忘记密码,无法登录,如何处理?

重启 TiDB 服务,配置文件中增加 -skip-grant-table=true 参数,无密码登录集群后,可以根据情况重建用户,或者重建 mysql.user 表,具体表结构搜索官网。

如何导出 TiDB 数据?

你可以通过以下方式导出 TiDB 数据:

如何从 DB2、Oracle 数据库迁移到 TiDB?

DB2、Oracle 到 TiDB 数据迁移(增量+全量),通常做法有:

  • 使用 Oracle 官方迁移工具,如 OGG、Gateway(透明网关)、CDC (Change Data Capture)。
  • 自研数据导出导入程序实现。
  • 导出 (Spool) 成文本文件,然后通过 Load infile 进行导入。
  • 使用第三方数据迁移工具。

目前看来 OGG 最为合适。

用 Sqoop 批量写入 TiDB 数据,虽然配置了 --batch 选项,但还是会遇到 java.sql.BatchUpdateExecption:statement count 5001 exceeds the transaction limitation 的错误,该如何解决?

  • 在 Sqoop 中,--batch 是指每个批次提交 100 条 statement,但是默认每个 statement 包含 100 条 SQL 语句,所以此时 100 * 100 = 10000 条 SQL 语句,超出了 TiDB 的事务限制 5000 条,可以增加选项 -Dsqoop.export.records.per.statement=10 来解决这个问题,完整的用法如下:

    1. sqoop export \
    2. -Dsqoop.export.records.per.statement=10 \
    3. --connect jdbc:mysql://mysql.example.com/sqoop \
    4. --username sqoop ${user} \
    5. --password ${passwd} \
    6. --table ${tab_name} \
    7. --export-dir ${dir} \
    8. --batch
  • 也可以选择增大 tidb 的单个事物语句数量限制,不过这个会导致内存上涨。

Dumpling 导出时引发上游数据库 OOM 或报错“磁盘空间不足”

该问题可能有如下原因:

  • 数据库主键分布不均匀,例如启用了 SHARD_ROW_ID_BITS
  • 上游数据库为 TiDB,导出表是分区表

在上述情况下,Dumpling 划分导出子范围时,会划分出过大的子范围,从而向上游发送结果过大的查询。请联系 AskTUG 社区专家获取实验版本的 Dumpling。

TiDB 有像 Oracle 那样的 Flashback Query 功能么,DDL 支持么?

有,也支持 DDL。详细参考 TiDB 历史数据回溯

在线数据同步

有没有现成的同步方案,可以将数据同步到 Hbase、Elasticsearh 等其他存储?

没有,目前依赖程序自行实现。

业务流量迁入

如何快速迁移业务流量?

我们建议通过 TiDB Data Migration 进行 MySQL -> TiDB 的业务数据的迁移;业务读写可以按照需求分阶段通过修改网络配置进行流量迁移,建议 DB 上层部署一个稳定的网络 LB(HAproxy、LVS、F5、DNS 等),这样直接修改网络配置就能实现无缝流量迁移。

TiDB 总读写流量有限制吗?

TiDB 读流量可以通过增加 TiDB server 进行扩展,总读容量无限制,写流量可以通过增加 TiKV 节点进行扩容,基本上写容量也没有限制。

Transaction too large 是什么原因,怎么解决?

TiDB 限制了单条 KV entry 不超过 6MB,可以修改配置文件中的 txn-entry-size-limit 配置项进行调整,最大可以修改到 120MB。

分布式事务要做两阶段提交,而且底层还需要做 Raft 复制。如果一个事务非常大,提交过程会非常慢,事务写冲突概率会增加,而且事务失败后回滚会导致不必要的性能开销。所以我们设置了 key-value entry 的总大小默认不超过 100MB。如果业务需要使用大事务,可以修改配置文件中的 txn-total-size-limit 配置项进行调整,最大可以修改到 10G。实际的大小限制还受机器的物理内存影响。

在 Google 的 Cloud Spanner 上面,也有类似的限制

如何批量导入?

导入数据的时候,可以分批插入,每批最好不要超过 1w 行。

TiDB 中删除数据后会立即释放空间吗?

DELETE,TRUNCATE 和 DROP 都不会立即释放空间。对于 TRUNCATE 和 DROP 操作,在达到 TiDB 的 GC (garbage collection) 时间后(默认 10 分钟),TiDB 的 GC 机制会删除数据并释放空间。对于 DELETE 操作 TiDB 的 GC 机制会删除数据,但不会释放空间,而是当后续数据写入 RocksDB 且进行 compact 时对空间重新利用。

Load 数据时可以对目标表执行 DDL 操作吗?

不可以,加载数据期间不能对目标表执行任何 DDL 操作,这会导致数据加载失败。

TiDB 是否支持 replace into 语法?

支持。

删除数据后查询速度为何会变慢?

删除大量数据后,会有很多无用的 key 存在,影响查询效率。要解决该问题,可以尝试开启 Region Merge 功能,具体可参考最佳实践中的删除数据部分。

数据删除最高效最快的方式?

在删除大量数据的时候,建议使用 Delete from t where xx limit 5000(xx 建议在满足业务过滤逻辑下,尽量加上强过滤索引列或者直接使用主键选定范围,如 id >= 5000*n+m and id <= 5000*(n+1)+m 这样的方案,通过循环来删除,用 Affected Rows == 0 作为循环结束条件,这样避免遇到事务大小的限制。如果一次删除的数据量非常大,这种循环的方式会越来越慢,因为每次删除都是从前向后遍历,前面的删除之后,短时间内会残留不少删除标记(后续会被 GC 掉),影响后面的 Delete 语句。如果有可能,建议把 Where 条件细化。可以参考官网最佳实践

TiDB 如何提高数据加载速度?

主要有两个方面:

  • 目前已开发分布式导入工具 TiDB Lightning,需要注意的是数据导入过程中为了性能考虑,不会执行完整的事务流程,所以没办法保证导入过程中正在导入的数据的 ACID 约束,只能保证整个导入过程结束以后导入数据的 ACID 约束。因此适用场景主要为新数据的导入(比如新的表或者新的索引),或者是全量的备份恢复(先 Truncate 原表再导入)。
  • TiDB 的数据加载与磁盘以及整体集群状态相关,加载数据时应关注该主机的磁盘利用率,TiClient Error/Backoff/Thread CPU 等相关 metric,可以分析相应瓶颈。