TiDB异常处理:transaction is too large

背景

由于TiDbiB是一个支持ACID的分布式数据库,受限于事务大小的严格控制,日常Hive与TiDB大批量数据交互的过程中,常常会出现如下错误:

Error Code:8004.transaction is too large

原因

以下摘自TiDB官方解释文档

由于分布式事务要做两阶段提交,并且底层还需要做Raft复制,如果一个事务非常大,会使得提交过程非常慢,并且会卡住下面的Raft复制流程。为了避免系统出现被卡住的情况,对事务的大小做了限制:

  • 单个事务包含的SQL语句不超过5000条(默认)
  • 单条KV entry不超过6MB(SQL层面:单行数据不大于6MB)
  • KV entry的总条数不超过30w(SQL层面:总的行数*(1+索引个数)<30w)
  • KV entry的总大小不超过100MB(SQL层面:一次提交的全部数据小于100MB)

注意:无论是大小限制还是行数限制,还要考虑TiDBit做编码以及事务额外Key的开销,建议每个事务的行数不超过200行,且单行数据小于100k,否则可能性能不佳。

解决方案

insert&select

--开启隐藏函数
set @@session.tidb_batch_insert = 1;
--事务完成后,关闭
set @@session.tidb_batch_insert = 0;

注意:insert会把大事务分批执行,避免超时的同时会导致事务原子性的丢失。

update&delete

for i from 0 to 23:
    while affected_rows <> 0:
        delete * from table where insert_time >= i:00:00 and insert_time < (i+1):00:00 limit 5000;
        affected_rows = select affected_rows()      

注意:通过循环方式删除数据可能会导致速度越来越慢,因为每次删除都是从前向后遍历,前面数据删除后,短时间内会残留删除标记(后续会被gc掉),从而影响后面的Delete语句。因此建议将where条件细化,见上伪代码。

你可能感兴趣的:(TiDB异常处理:transaction is too large)