技术分享|tidb对大事务的简单拆分

爱可生云数据库      2022-02-09     324

关键词:

作者:杨涛涛

资深数据库专家,专研 MySQL 十余年。擅长 MySQL、PostgreSQL、MongoDB 等开源数据库相关的备份恢复、SQL 调优、监控运维、高可用架构设计等。目前任职于爱可生,为各大运营商及银行金融企业提供 MySQL 相关技术支持、MySQL 相关课程培训等工作。

本文来源:原创投稿

*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。


长期以来,在 MySQL 的开发规范里一般都会这么写: 禁止大事务!话题转到 TiDB ,依然应该是:禁止大事务!

TiDB 由于事务本身分布式特性,加之后台 RAFT 复制导致的写放大,非常不推荐使用大事务。

TiDB 在4.0 之前的版本对事务要求有些过于细致,比如:
  1. 单个事务包含的 SQL 语句不超过5000条
  2. 单条 KV entry 不超过6MB
  3. KV entry 的总条数不超过30w
  4. KV entry 的总大小不超过100MB
上面的几点限制会导致一些 DML 语句写入受阻,比如下面这三类经典无过滤条件语句:
  1. insert ... select ... where 1
  2. update ... where 1
  3. delete from ... where 1
非常容易出现事务过大的错误: ERROR 8004 (HY000): transaction too large, len:300001。 一般有如下方法来规避这个问题:
  1. 针对Insert、delete 语句开启无安全保证的dml batch 特性:TiDB_batch_insert、TiDB_batch_delete。
  2. 分块拆分整条update 语句。

在4.0 之后的版本里,除了单个kv entry 大小依然限制为最大6MB,其他几个限制全部被取消。

只需要在配置文件里加上如下选项就可涵盖大部分事务:

performance.txn-total-size-limit: 10737418240(范围 1G 到10G)

那是不是4.0 版本后就可以随意写事务了? 当然不是! 由于TiDB 的写放大,也会连带导致内存占用成倍增长,对其他业务会有很大影响,所以TiDB对最大事务支持硬性限制其为10G。比如用DM 来同步MySQL数据到TiDB,大事务会导致内存加大,写入延迟剧增,进而影响其他的写性能。

所以还是得禁止大事务,拆分为小事务批量处理。

那如何对大事务进行拆分呢? 单从业务方面讲,业务类型不同,对应的拆分方法不同,可能一本书都写不完。 这里我仅仅从数据库角度,细分为从表角度,再进一步到DML语句角度如何拆分。

上面列的这三条经典语句看起来很简单,但是没有过滤条件,如果表索引数非常多,即使表记录数不大,也会是一个大事务,只不过这个事务只包含一条DML语句。但是这类语句的拆分实际上要看表结构怎么定义,分为三种:

  1. 有主键,并且主键连续
  2. 有主键,主键不连续
  3. 表无主键(类似第一种)
第一种最容易拆分,根据主键来划分不同的块即可。

举个例子:

表t1 有100W 条记录,除主键外有6个索引,对表t1 进行update :

update ytt.t1 set log_date = current_date() - interval ceil(rand()*1000) day where 1;

在默认自动提交下,这条语句其实就是隐式大事务语句,在内部转换为 :

begin

update ytt.t1 set log_date = current_date() - interval ceil(rand()*1000) day where 1;

commit;

假设表t1主键为自增且连续,那很简单,把这个事务分为10个小事务,每次更新10W条记录,而不是一次性更新100W条。脚本大致如下:

root@ytt-ubuntu:~/scripts# cat update_table_batch
#!/bin/sh
# TiDB 拆分更新
for i in `seq 1 10`;do
    min_id=$(((i-1)*100000+1))
    max_id=$((i*100000))
    queries="update t1 set log_date = date_sub(current_date(), interval ceil(rand()*1000) day)  \
        where id >=$min_id and id<=$max_id;" 

    mysql --login-path=TiDB_login -D ytt -e "$queries" &
done
第二种,针对不连续的自增主键场景。

第一种最为常见,在 TiDB 里强烈不推荐使用连续自增字段来做主键,这会导致潜在的单 region 写热点问题。所以自增主键推荐使用 auto_random 特性来随机写入,避免连续性。

上面脚本里列出的方法就变得不太适合。那该怎么拆呢? 可以稍加变通,用窗口函数 row_number() 来补模拟主键,更新表改为 t2 ,改写后的脚本大致如下:

root@ytt-ubuntu:~/scripts# cat update_table_batch
#!/bin/sh
# TiDB 拆分更新
for i in `seq 1 10`;do
    min_id=$(((i-1)*100000+1))
    max_id=$((i*100000))
    queries="update t2 a, (select *,row_number() over(order by id) rn from t2) b set a.log_date =  \
        date_sub(current_date(), interval ceil(rand()*1000) day)  \
        where a.id = b.id and (b.rn>=$min_id and b.rn<=$max_id);"
    mysql --login-path=TiDB_login -D ytt -e "$queries" &
done

其实以上两种思路已经包含了绝大多数拆分场景。 MySQL 或者 TiDB 对于没有主键的表都默认包含一个隐式自增 ID 来区分行之间关系,所以为了避免在DML层来增加复杂的拆分策略,依然强烈建议使用显式主键!

结语

虽然 TiDB 4.0 版本后,对大事务支持已经非常好,但这不是可以随便用大事务的理由,还是要做好表设计提前拆、检索表数据提前拆等拆分策略,才能更好的让数据库服务好业务。

tidb学习笔记-体系架构

...xff1a;分布式,高度兼容MySQL,高可用,支持ACID事务(事务模型:Percolator),丰富的工具链生态一、TiDBSQL层,解析SQL,将数据读取请求发给TiKV/TiFlash功能:处理客户端的连接SQL语句的解析和... 查看详情

tidb孵化器项目发起,快来孵化你的技术理想

TiDB社区由开发者、用户和TiDB生态中的合作伙伴组成,致力于构建“面向未来的数据库”,以及打造TiDB的可持续发展生态。在整个社区的不断努力和帮助下,TiDB的生态也在不断发展,越来越多的开源项目成为TiDB大家庭的一员。... 查看详情

数据库必知必会:tidbtikv分布式事务(代码片段)

(数据库必知必会:TiDB(4)TiKV分布式事务)分布式事务存在的问题假设有这样一个事务:begin:updatepersonsetname=Tomwhereid=1;updatepersonsetname=Jackwhereid=2;commit;由于数据在TiKV中是分布式存储的,那么这两条数据就有可能分布在TiKV的两个实... 查看详情

技术分享innodbcluster如何高效加载数据

参考技术A一行命令搞定InnoDBCluster数据快速加载。InnoDBCluster8.0经过一系列的优化已足够稳定,早期版本常因网络延迟、闪断等问题造成集群不稳定,也曾遇到客户因网络缓解问题导致节点频繁被踢,可用性得不到保障,不得不使... 查看详情

云图说丨云数据库gaussdb(formysql)事务拆分大揭秘

...离)_华为云点击关注,第一时间了解华为云新鲜技术~  查看详情

云图说丨云数据库gaussdb(formysql)事务拆分大揭秘

...离)_华为云点击关注,第一时间了解华为云新鲜技术~  查看详情

mysql和tidb在snapshot隔离级别上的区别(代码片段)

如果一个事务包含多条SQL语句,在snapshot隔离级别上,mysql并不是事务开始的时候获得一个snapshot而是在执行第一条SQL语句的时候获得snapshot的;而TiDB是在事务开始的时候获得一个snapshot参考https://pingcap.com/blog-cn/tikv-sour... 查看详情

dumpling导出表内并发优化丨tidb工具分享

李淳竹(lichunzhu),TiDB研发工程师SIG组:MigrateSIGCommunity,主要涵盖TiDB数据处理工具,包含TiDB数据备份/导入导出,TiDB数据变更捕获,其他数据库数据迁移至TiDB等前言Dumpling是由Go语言编写的用于对... 查看详情

tidb在微众银行核心批量场景的实践

...据PingCAPDevCon2021上来自微众银行资深数据库架构师黄蔚的分享整理而成,主要阐述TiDB在微众银行的应用实践,包括微众银行选择TiDB的背景和TiDB的部署架构,以及TiDB在贷款核心批量场景的应用,最后分享了基于TiDB... 查看详情

一文教你迅速解决分布式事务xa一致性问题

欢迎大家前往腾讯云技术社区,获取更多腾讯海量技术实践干货哦~作者:腾讯云数据库团队 近日,腾讯云发布了分布式数据库解决方案(DCDB),其最明显的特性之一就是提供了高于开源分布式事务XA的性能。大型业务系统... 查看详情

应用程序拆分挑战 - 快速+简单的 RPC 技术?

】应用程序拆分挑战-快速+简单的RPC技术?【英文标题】:TheApplicationSplitChallenge-fast+easyRPCtechnology?【发布时间】:2011-01-2409:25:43【问题描述】:以下内容试图了解哪些技术适用于特定(如概述的)分布式/RPC问题。如果有不清楚... 查看详情

带着问题读tidb源码:hive元数据使用tidb启动报错

...到用户反馈使用TiDB作为Hivemetastore数据库时设置SERIALIZABLE事务隔离级别失败。并且用户根据文档建议进行SETGLOBALtidb_skip_isolation_le 查看详情

技术分享|update更新慢死锁等问题的排查思路分享

本文来源:原创投稿*GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。内容提纲一、简介二、Update生命周期2.1连接器2.2分析器2.3优化器2.4执行器2.4.1事务执行阶段2.4.2事务提交阶段2.4.3假设事务ROLLB... 查看详情

tidb整体架构及主要特性

参考技术A首先,贴出的是TiDB的架构图。TiDB集群主要包括三个核心组件:TiDBServer,PDServer和TiKVServer。此外,还有用于解决用户复杂OLAP需求的TiSpark组件。TiDBServer负责接收SQL请求,处理SQL相关的逻辑,并通过PD找到存储计算所需数... 查看详情

tidb在ebay丨亿优百倍:商品数据服务缓存与代码优化

“亿优百倍”是eBay智能营销团队推出的系列文章,分享了在营销商品数据服务系统的架构、设计、代码方面的一些理解和研究。在上期的亿优百倍|商品数据服务TiDB性能优化(点击阅读)里,我们分享了对TiDB进行调优的方法,以提... 查看详情

dm中relaylog性能优化实践丨tidb工具分享(代码片段)

将转换后的binlogevent使用binlogwriter以relaylogfile的形式存储在本地的relaydirectory中。的机制,读取最近写入的文件并非通过磁盘,而是读取OS内存中的缓存,因此理论上影响有限。的存在,应用本身再增加一层缓存对latency的影响有... 查看详情

tidb6.0实战分享丨冷热存储分离解决方案(代码片段)

结论先行TiDB6.0正式提供了数据放置框架(PlacementRulesinSQL)功能,用户通过SQL配置数据在TiKV集群中的放置位置,可以对数据进行直接的管理,满足不同的业务场景需要。如:1.冷热分离存储,降低存储... 查看详情

在entityframework中使用事务

...为想使用EntityFramework的朋友在前面探路,分享的东西虽然技术含量不高,但都是经过实践检验的。在EntityFramework中使用事务很简单,将操作放在TransactionScope中,并通过Complete()方法提交事务即可。示例代码如下:using(BlogDbContextcon... 查看详情