title | summary | aliases | |
---|---|---|---|
迁移常见问题 |
介绍 TiDB 迁移中的常见问题。 |
|
TiDB 支持绝大多数 MySQL 语法,一般不需要修改代码。
重启 TiDB 服务,配置文件中增加 -skip-grant-table=true
参数,无密码登录集群后,可以根据情况重建用户,或者重建 mysql.user 表,具体表结构搜索官网。
TiDB 目前暂时不支持 select into outfile
,可以通过以下方式导出 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.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
来解决这个问题,完整的用法如下:{{< 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 的单个事物语句数量限制,不过这个会导致内存上涨。
该问题是由于数据库主键分布不均匀,Dumpling 划分导出子范围时出现过大的子范围引起的。请尝试分配更大的磁盘空间,或者联系 AskTUG 社区专家 获取实验版本的 Dumpling。
有,也支持 DDL。详细参考 TiDB 历史数据回溯。
没有,目前依赖程序自行实现。
我们建议通过 TiDB Data Migration 进行 MySQL -> TiDB 的业务数据的迁移;业务读写可以按照需求分阶段通过修改网络配置进行流量迁移,建议 DB 上层部署一个稳定的网络 LB(HAproxy、LVS、F5、DNS 等),这样直接修改网络配置就能实现无缝流量迁移。
TiDB 读流量可以通过增加 TiDB server 进行扩展,总读容量无限制,写流量可以通过增加 TiKV 节点进行扩容,基本上写容量也没有限制。
TiDB 限制了单条 KV entry 不超过 6MB。
分布式事务要做两阶段提交,而且底层还需要做 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 操作,这会导致数据加载失败。
支持,但是 load data 不支持 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 条件细化。可以参考官网最佳实践。
主要有两个方面:
- 目前已开发分布式导入工具 Lightning,需要注意的是数据导入过程中为了性能考虑,不会执行完整的事务流程,所以没办法保证导入过程中正在导入的数据的 ACID 约束,只能保证整个导入过程结束以后导入数据的 ACID 约束。因此适用场景主要为新数据的导入(比如新的表或者新的索引),或者是全量的备份恢复(先 Truncate 原表再导入)。
- TiDB 的数据加载与磁盘以及整体集群状态相关,加载数据时应关注该主机的磁盘利用率,TiClient Error/Backoff/Thread CPU 等相关 metric,可以分析相应瓶颈。
可以设置并行 GC,加快对空间的回收速度。默认并发为 1,最大可调整为 tikv 实例数量的 50%。可使用 update mysql.tidb set VARIABLE_VALUE="3" where VARIABLE_NAME="tikv_gc_concurrency";
命令来调整。