tidb使用坑记录
1、对硬盘要求很高,没上SSD硬盘的不建议使用
2、不支持分区,删除数据是个大坑。
解决方案:set @@session.tidb_batch_delete=1;
3、插入数据太大也会报错
解决方案:set @@session.tidb_batch_insert=1;
4、删除表数据时不支持别名
delete from 表名 表别名 where 表别名.col = '1' 会报错
5、内存使用有问题,GO语言导致不知道回收机制什么时候运作。内存使用过多会导致TIDB当机(这点完全不像MYSQL)
测试情况是,32G内存,在10分钟后才回收一半。
6、数据写入的时候,tidb压力很大, tikv的CPU也占用很高
7、不支持GBK
8、不支持存储过程
9、列数支持太少,只支持100列,和oralce/mysql的1000列少太多(Oracle 最大列数为 1000;MySQL对于每个表具有4096个列的硬限制, 其中InnoDB每个表的限制为1017列, 最大行大小限制为65,535字节)
外面文章的一些建议
3TiKV+3PD+2TiDB
在有了 TiSpark 之后,我们便利用 TiSpark 将中间表缓存为 Spark 的内存表,只需要将最后的数据落地回 TiDB,再执行 Merge 操作即可,这样省掉了很多中间数据的落地,大大节省了很多脚本执行的时间
在查询速度解决之后,我们发现脚本中会有很多针对中间表 update 和 delete 的语句。目前 TiSpark 暂时不支持 update 和 delete 的操作(和 TiSpark 作者沟通,后续会考虑支持这两个操作),
我们便尝试了两种方案,一部分执行类似于 Hive,采用 insert into 一张新表的方式来解决;另外一部分,我们引入了 Spark 中的 Snappydata 作为一部分内存表存储,
在 Snappydata 中进行 update 和 delete,以达到想要的目的。因为都是 Spark 的项目,因此在融合两个项目的时候还是比较轻松的。
最后,关于实时的调度工具,目前我们是和离线调度一起进行调度,这也带来了一些问题,每次脚本都会初始化一些 Spark 参数等,这也相当耗时。在未来,我们打算采用 Spark Streaming 作为调度工具,
每次执行完成之后记录时间戳,Spark Streaming 只需监控时间戳变化即可,能够避免多次初始化的耗时,通过 Spark 监控,我们也能够清楚的看到任务的延迟和一些状态,这一部分将在未来进行测试。
简介
根据网上一些使用案例列出目前TiDB和mysql在使用上的区别和目前的遇到的常见问题及解决方案,当然具体的使用问题还需要大量的线下测试才能确认。
问题类型 | 问题描述 | 原因及解决办法 |
---|---|---|
DDL | 在一个 DDL 里不能对多个列或者多个索引做操作。 | ADD/DROP INDEX/COLUMN 操作目前不支持同时创建或删除多个索引或列, 需要拆分单独执行,官方表示 3.0 版本有计划改进。 |
建表语句执行速度相比 MySQL 较慢 | 多台 TiDB 的时候,Owner 和接收 create table 语句的 TiDB Server 不在一台 Server 上时, 可能比 MySQL 慢一些,每次操作耗时在 0.5s 左右,官方表示会在后续的版本中不断完善。 | |
大表建索引时对业务有影响 | 官方建议在业务低峰期操作,在 2.1 版本中已经增加了操作优先级以及并发读的控制,情况有改善。 | |
TiDB 对于 MySQL 用户授权 SQL 语法的兼容支持尚不完善, 目前不支持 SHOW CREATE USER 语法, 有时候不得不读取系统表(mysql.user)来查看一个数据库账户的基本信息 | 希望后续版本优化 | |
DML | 部分操作符查询优化器支持不够好,比如 or 操作符会使用 TableScan, 改写成 union all 可避免。 | 官方表示目前使用 or 操作符确实在执行计划上有可能不准确, 已经在改进计划中,后续 3.0 版本会有优化。 |
MySQL 事务中,可以通过影响条数,作为写入(或修改)是否成功的依据; 而在 TiDB 中,这却是不可行的。 | 原因: 对于 MySQL,当更新某条记录时,会先获取该记录对应的行级锁(排他锁), 获取成功则进行后续的事务操作,获取失败则阻塞等待。 对于 TiDB,使用 Percolator 事务模型:可以理解为乐观锁实现,事务开启、 事务中都不会加锁,而是在提交时才加锁。 解决方案: 在业务层,可以借助分布式锁,实现串行化处理,但是会增加开发成本。 | |
对于热数据,数据量一般不大,但是查询频度很高,比如查询 sql 为: 这个在 MySQL 中很高效的查询,在 TiDB 中虽然也可从索引检索, 但其耗时却不尽人意(百万级数据量,耗时百毫秒级)。 | 原因:在 TiDB 中,底层索引结构为 LSM-Tree。当从内存级的 C0 层查询不到数据时, 会逐层扫描硬盘中各层;且 merge 操作为异步操作,索引数据更新会存在一定的延迟,可能存在无效索引。 由于逐层扫描和异步 merge,使得查询效率较低。 解决方案: 尽可能缩小过滤范围,比如结合异步 job 获取记录频率,在保证不遗漏数据的前提下, 合理设置 execute_time 筛选区间,例如 1 小时,sql 改写为: | |
select count(1) tidb查询慢 | 原因:和上面类似。 tidb因为存储结构和查询方式的不同,tidb其实是暴力扫表。很多使用方也都反应慢, 这个是目前的TiDB的一个常见的问题。这里给出官方的解决方案:
| |
尚不支持的sql语法: |
| |
PD | 重启一个 PD 节点的时候,业务能捕捉到 PD 不可用的异常, 会报 PD server timeout 。 | 因为重启的是 Leader 节点,所以重启之前需要手动切换 Leader,然后进行重启。 官方建议这里可以通过重启前做 Leader 迁移来减缓, 另外后续 TiDB 也会对网络通讯相关参数进行梳理和优化。 |
pd-ctl 命令行参数解析严格,多一个空格会提示语法错误。 | 官方表示低版本中可能会有这个问题,在 2.0.8 及以上版本已经改进。 | |
TiDB | 现在 TiDB 的 GC 对于每个 kv-instance 是单线程的, 当业务删除数据的量非常大时,会导致 GC 速度较慢, 很可能 GC 的速度跟不上写入。 | 目前可以通过增多 TiKV 个数来解决,长期需要靠 GC 改为多线程执行,后续版本会支持。 |
TiKV | 存储空间放大问题 | 该问题属于 RocksDB,RocksDB 的空间放大系数最理想的值为 1.111, 官方建议在某些场景下通过 TiKV 开启 RocksDB 的 dynamic-level-bytes 以减少空间放大。 |
TiKV 容易发生 Write Stall | 原因: TiKV 底层有 2 个 RocksDB 作为存储。新写的数据写入 L0 层,当 RocksDB 的 L0 层数量达到一定数量, 就会发生减速,更高则发生 Stall,用来自我保护。 生 L0 文件过多可能的原因有 2 个:
解决: TiKV调优:
| |
添加 TiKV 节点后需要较长时间才能完成数据再平衡 | 1TB 数据大约需要 24 个小时才能完成拷贝,建议在低峰期引入 |
TiDB和Mysql优缺点对比
简单总结一下TiDB的优缺点:
TiDB优点
- 高度兼容mysql协议,迁移成本低
- 高可用:相比于传统主从(M-S)复制方案,基于 Raft 的多数派选举协议可以提供金融级的 100% 数据强一致性保证,且在不丢失大多数副本的前提下,可以实现故障的自动恢复(auto-failover),无需人工介入。
- 支持海量数据,可拓展性强:分布式数据库,可通过增加TiKV节点拓展,支持分裂和自动迁移,对业务基本无感知。
- 和传统的分库分表,相比业务拓展性较强:传统的分库分表技术,开发和维护成本都较高,业务侵入性也较大,使用TiDB会明显降低 RD 和 DBA 的开发维护成本。
- 分布式事务
TiDB的不足
- 对机器配置门槛要求较高,特别是内存和CPU的要求很高,当数据量不大时会增加机器的资源使用成本。
- TiDB对sql的支持尚不完善,对一些sql的执行性能并不理想,一些复杂sql需要重新设计,还有一些mysql的功能并不支持。
- TiDB技术较新,尚在不断优化中,因此也容易踩坑。
综合
综上所述,个人认为和mysql相比,
- TiDB目前更适合TB级的海量数据处理,数据量越大,使用场景和优势越明显,
- 也比较适合对查询性能要求不高的数据分析场景或离线计算场景
- 即时场景下查询上最适合海量数据下进行多维度的精确查询
- 整体而言TiDB技术仍不能算成熟,目前还在快速的更新和迭代过程中,容易采坑,建议引入也是先从离线业务->非核心业务->核心业务的使用过程。