title | summary | aliases | |
---|---|---|---|
迁移常见问题 |
介绍 TiDB 迁移中的常见问题。 |
|
本文介绍 TiDB 数据迁移中的常见问题。
如果要查看迁移相关工具的常见问题,请参考以下链接:
TiDB 支持绝大多数 MySQL 语法,一般不需要修改代码。
在没有其他逻辑出错的情况下,重试、EOF 可能是由网络问题引起的,建议首先使用相关工具排查网络连通状况。以下示例使用 iperf 进行排查:
-
在出现重试、EOF 错误的服务器端节点执行以下命令:
{{< copyable "shell-regular" >}}
iperf3 -s
-
在出现重试、EOF 错误的客户端节点执行以下命令:
{{< copyable "shell-regular" >}}
iperf3 -c <server-IP>
下面是一个网络连接良好的客户端节点的输出:
$ iperf3 -c 192.168.196.58
Connecting to host 192.168.196.58, port 5201
[ 5] local 192.168.196.150 port 55397 connected to 192.168.196.58 port 5201
[ ID] Interval Transfer Bitrate
[ 5] 0.00-1.00 sec 18.0 MBytes 150 Mbits/sec
[ 5] 1.00-2.00 sec 20.8 MBytes 175 Mbits/sec
[ 5] 2.00-3.00 sec 18.2 MBytes 153 Mbits/sec
[ 5] 3.00-4.00 sec 22.5 MBytes 188 Mbits/sec
[ 5] 4.00-5.00 sec 22.4 MBytes 188 Mbits/sec
[ 5] 5.00-6.00 sec 22.8 MBytes 191 Mbits/sec
[ 5] 6.00-7.00 sec 20.8 MBytes 174 Mbits/sec
[ 5] 7.00-8.00 sec 20.1 MBytes 168 Mbits/sec
[ 5] 8.00-9.00 sec 20.8 MBytes 175 Mbits/sec
[ 5] 9.00-10.00 sec 21.8 MBytes 183 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate
[ 5] 0.00-10.00 sec 208 MBytes 175 Mbits/sec sender
[ 5] 0.00-10.00 sec 208 MBytes 174 Mbits/sec receiver
iperf Done.
如果输出显示网络带宽较低、带宽波动大,各组件日志中就可能出现大量重试、EOF 错误。此时你需要咨询网络服务供应商以提升网络质量。
如果输出的各指标良好,请尝试更新各组件版本。如果更新后仍无法解决问题,请移步 AskTUG 论坛寻求帮助。
重启 TiDB 服务,配置文件中增加 -skip-grant-table=true
参数,无密码登录集群后,可以根据情况重建用户,或者重建 mysql.user 表,具体表结构搜索官网。
你可以通过以下方式导出 TiDB 数据:
- 参考 MySQL 使用 mysqldump 导出某个表的部分数据,使用 mysqldump 加 where 条件导出。
- 使用 MySQL client 将 select 的结果输出到一个文件。
DB2、Oracle 到 TiDB 数据迁移(增量+全量),通常做法有:
- 使用 Oracle 官方迁移工具,如 OGG、Gateway(透明网关)、CDC (Change Data Capture)。
- 自研数据导出导入程序实现。
- 导出 (Spool) 成文本文件,然后通过 Load infile 进行导入。
- 使用第三方数据迁移工具。
目前看来 OGG 最为合适。
用 Sqoop 批量写入 TiDB 数据,虽然配置了 --batch
选项,但还是会遇到 java.sql.BatchUpdateException: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
来解决这个问题,完整的用法如下:{{< copyable "shell-regular" >}}
sqoop export \ -Dsqoop.export.records.per.statement=10 \ --connect jdbc:mysql://mysql.example.com/sqoop \ --username sqoop ${user} \ --password ${passwd} \ --table ${tab_name} \ --export-dir ${dir} \ --batch
-
也可以选择增大 tidb 的单个事物语句数量限制,不过这个会导致内存上涨。
该问题可能有如下原因:
- 数据库主键分布不均匀,例如启用了 SHARD_ROW_ID_BITS
- 上游数据库为 TiDB,导出表是分区表
在上述情况下,Dumpling 划分导出子范围时,会划分出过大的子范围,从而向上游发送结果过大的查询。请联系 AskTUG 社区专家获取实验版本的 Dumpling。
有,也支持 DDL。详细参考 TiDB 历史数据回溯。
没有,目前依赖程序自行实现。
我们建议通过 TiDB Data Migration 进行 MySQL -> TiDB 的业务数据的迁移;业务读写可以按照需求分阶段通过修改网络配置进行流量迁移,建议 DB 上层部署一个稳定的网络 LB(HAproxy、LVS、F5、DNS 等),这样直接修改网络配置就能实现无缝流量迁移。
TiDB 读流量可以通过增加 TiDB server 进行扩展,总读容量无限制,写流量可以通过增加 TiKV 节点进行扩容,基本上写容量也没有限制。
TiDB 限制了单条 KV entry 不超过 6MB,可以修改配置文件中的 txn-entry-size-limit
配置项进行调整,最大可以修改到 120MB。
分布式事务要做两阶段提交,而且底层还需要做 Raft 复制。如果一个事务非常大,提交过程会非常慢,事务写冲突概率会增加,而且事务失败后回滚会导致不必要的性能开销。所以我们设置了 key-value entry 的总大小默认不超过 100MB。如果业务需要使用大事务,可以修改配置文件中的 txn-total-size-limit
配置项进行调整,最大可以修改到 10G。实际的大小限制还受机器的物理内存影响。
在 Google 的 Cloud Spanner 上面,也有类似的限制。
导入数据的时候,可以分批插入,每批最好不要超过 1w 行。
DELETE,TRUNCATE 和 DROP 都不会立即释放空间。对于 TRUNCATE 和 DROP 操作,在达到 TiDB 的 GC (garbage collection) 时间后(默认 10 分钟),TiDB 的 GC 机制会删除数据并释放空间。对于 DELETE 操作 TiDB 的 GC 机制会删除数据,但不会释放空间,而是当后续数据写入 RocksDB 且进行 compact 时对空间重新利用。
不可以,加载数据期间不能对目标表执行任何 DDL 操作,这会导致数据加载失败。
支持。
删除大量数据后,会有很多无用的 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 Lightning,需要注意的是数据导入过程中为了性能考虑,不会执行完整的事务流程,所以没办法保证导入过程中正在导入的数据的 ACID 约束,只能保证整个导入过程结束以后导入数据的 ACID 约束。因此适用场景主要为新数据的导入(比如新的表或者新的索引),或者是全量的备份恢复(先 Truncate 原表再导入)。
- TiDB 的数据加载与磁盘以及整体集群状态相关,加载数据时应关注该主机的磁盘利用率,TiClient Error/Backoff/Thread CPU 等相关 metric,可以分析相应瓶颈。