文档目录

迁移常见问题

全量数据导出导入

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

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

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

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

如何导出 TiDB 数据?

TiDB 目前暂时不支持 select into outfile,可以通过以下方式导出 TiDB 数据:参考 MySQL 使用 mysqldump 导出某个表的部分数据,使用 mysqldump 加 where 条件导出,使用 MySQL client 将 select 的结果输出到一个文件。

如何从 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 来解决这个问题,完整的用法如下:

    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 导出大表时引发上游数据库报错“磁盘空间不足”

该问题是由于数据库主键分布不均匀,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。

分布式事务要做两阶段提交,而且底层还需要做 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 语法?

支持,但是 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 条件细化。可以参考官网最佳实践

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

主要有两个方面:

  • 目前已开发分布式导入工具 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"; 命令来调整。