iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >如何理解TiDB的分布式事务模型
  • 467
分享到

如何理解TiDB的分布式事务模型

2024-04-02 19:04:59 467人浏览 泡泡鱼
摘要

本篇内容介绍了“如何理解TiDB的分布式事务模型”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!在传统关系型

本篇内容介绍了“如何理解TiDB的分布式事务模型”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

在传统关系型数据库领域,我们常常通过配置事务的隔离级别来解决脏读、幻读、不可重复读的问题。不同的事务隔离级别对应解决问题的力度是不一样的,下表是不同事务隔离级别对脏读、幻读、不可重复读的容忍度,我们一起看一下:

如何理解TiDB的分布式事务模型

注意:

Repeatable read的读会一直到事务结束才释放;

Read committed的读锁不等到事务结束,而是读取完成后立即释放。

当然,传统数据库解决并发控制的手段还有mvcc,这里就不展开了。

上面我提到了读锁,写锁、GAP锁,实际上锁的种类远远不止这些。对于我们开发者来讲,经常会谈到乐观锁和悲观锁。乐观锁实际上是不加锁的,悲观锁需要真正的加锁。而在分布式数据库领域,同样需要并发控制,同样也有乐观事务和悲观事务。

就TiDB来说,v3.0版本开始支持悲观事务,从v3.0.8开始,新搭建的TiDB集群已经默认使用悲观事务了。

传统数据库加锁

传统数据库的乐观锁,主要是在表中加入一个版本号字段,在更新的时候根据更新结果来进行判断是否成功。比如我们有一张表table_a,  我们在其中加一个version字段,下面是table_a表的1条记录

表格

idnameversion
1jinjunzhu4

我们更新这条id=1的记录,sql如下:

update table_a set name='xiaoming',version = version + 1 where id=1 and version=4

这时如果SQL执行结果返回更新行数是0,说明别的事务已经更新了version字段,写冲突产生,业务代码必须处理这个冲突。高并发下如果对同一条记录的修改操作非常多,势必造成大量写失败。所以乐观锁更适合读多写少的场景。

传统数据库的悲观锁,是用物理加锁的方式,还是上面的表,不需要version字段了,假如有2条记录:

idname
1jinjunzhu
2xiaoming

这时加入我们要同时更新id=1的记录和id=2的记录,如果在一个事务内完成,加锁sql如下:

select * from table_a where id in(1, 2) for update; update table_a set name = 'zhangsan' where id=1; update table_a set name = 'lisi' where id=2;

悲观锁的问题是遇到长事务,其他事务需要较长时间的锁等待,所以oracle提供了下面的优化,即发现待修改数据被锁定后立刻返回失败:

select * from table_a for update nowait

Percolator模型

Percolator模型是Google提出的构建在BigTable之上的分布式事务解决方案。Google的论文如下,文章链接见延伸阅读[1]:

《Large-scale Incremental Processing Using Distributed Transactions and Notifications》

我们以经典的电商系统为例,假如系统中有订单、账户和库存3张表,用户一次购物需要增加1条订单记录,账户表需要扣减金额,库存表需要扣减库存,而这3张表要操作的记录分别在分布式数据库的3个切片上,这时就需要应对分布式事务了。

我们看一下Percolator算法模型:

如何理解TiDB的分布式事务模型

初始阶段

初始阶段,我们假设订单表记录订单数量是0,账户表记录账户金额1000,库存表记录商品数量是100,客户下了1个订单后,订单表增加1个订单,账户表扣除金额100,库存表扣减商品数量1。各个表的初始数据如下表:

如何理解TiDB的分布式事务模型

上面表格中,":"前面是用时间戳表示的数据版本,后面是数据值。第一列是表名,第二列的低版本保存了数据,第三列列保存了事务操作给数据加的锁。第四列的高版本保存了指向保存数据版本的指针,比如6这个版本保存了指向了5这个版本数据的指针  6:data@5。

Prewrite阶段

在Prewrite阶段,协调节点向每个切片发送Prewrite命令。Percolator定义了 primary lock  即主锁的概念,Prewrite阶段,每个分布式事务只能有一个要修改的数据行可以获得主锁,本案例假如订单表获得了主锁,其他表的锁是指向这个主锁的指针,叫做  secondary lock,如下表:

如何理解TiDB的分布式事务模型

Prewrite阶段,每个要修改的数据行会写日志,并且根据时间戳记录事务的私有版本,这里的私有版本就是7,这样其他事务就不能操作这三条数据了。

注意,获取主锁时,如果出现了下面的情况,就会加锁失败:

1.其他事务已经加锁;

2.本次事务开始之后,要更新的数据被其他数据更新了。

commit阶段

在commit阶段,协调节点只需要跟拥有primary lock的切片进行通信,所以本案例只需要跟订单表所在切片通信。这时数据如下表:

如何理解TiDB的分布式事务模型

我们注意到order表的锁没有了,而且增加了版本8指向版本7。说明订单表已经提交成功,没有私有版本了,但是账户表和库存表的私有版本还在。这是因为Percolator模型并不会同步commit账户表和库存表,而是启动异步线程来commit这两张表并清理锁。如果订单表提交失败,账户表和库存表也都需要回滚。

提交成功后,最终数据如下表:

如何理解TiDB的分布式事务模型

commit阶段,因为协调节点只需要跟拥有主锁的切片(这里是订单表所在切片)进行通信,保证了原子性,这样就避免了commit时节点不能全部成功导致的数据不一致问题。

而Prewrite阶段记录了日志和私有版本,如果账户表和库存表所在切片commit失败,可以根据日志进行再次commit,这样就保证了数据最终一致。

这里要注意2点:

1.主锁的选择是随机的,比如本例中并不一定会选择订单表;

2.协调节点发送commit后订单表先提交成功,这时如果其他事务要读取账户服务和库存服务的2条数据,虽然2条数据上面还有lock,但是查找primary@order.bal发现已提交,所以是可以读取的。不过读取时需要做一下secondary  lock清理工作。

TiDB乐观事务模型

上面我们分析了Percolator模型,TiDB的乐观事务正是使用了Percolator模型。

TiDB支持MVCC,事务启动的时候,会使用一个时间戳start_ts作为当前事务ID,同时作为MVCC的快照版本,之后的读请求会读取当前快照版本下的数据,数据校验成功后客户端进行两阶段commit,我们看一下下面的时序图:

如何理解TiDB的分布式事务模型

第一阶段,TiDB收到客户端请求后,首先会从缓存的待修改key中找出第一个发送prewrite请求,这个key加primary  lock后返回成功。然后TiDB会对这个事务其他的所有的key发送prewrite请求,这些key加secondary lock后返回成功。

第二阶段,prewrite成功后,TiDB首先会从PD获取一个时间戳作为当前事务的commit_ts,然后向primary lock  key发送commit请求,primary lock key提交数据成功后清理掉primary lock返回成功。TiDB收到primary lock  key的成功消息后给客户端返回成功。

乐观事务的冲突检测主要是在prewrite阶段,如果检测到当前的key已经加锁,会有一个等待时间,这个时间过后如果还没有获取到锁,就返回失败。因此当多个事务修改同一个key时,必然导致大量的锁冲突。

注意:TiDB也有重试机制,默认是关闭的。TiDB的重试会重新获取start_ts,但是不会重新读取数据,因此不能保证可重复读的隔离级别。详细参考TiDB官方文档。

TiDB悲观事务模型

TiDB从v3.0 版本开始,引入了悲观事务。

注意:v3.0.7及之前版本创建的集群升级到更高版本后,默认还是采用乐观事务,只有新创建集群才会默认使用悲观事务。我们也可以采用下面命令来开启悲观事务。下面第1个语句会修改TiDB系统参数,后面2个语句会忽略系统参数,优先级更高:

SET GLOBAL tidb_txn_mode = 'pessimistic';

BEGIN PESSIMISTIC;

BEGIN OPTIMISTIC;

为了兼容Mysql,TiDB的悲观事务和mysql很类似。悲观事务支持可重复读和读已提交两种隔离级别,默认使用可重复读。TiDB中乐观事务和悲观事务可以共存,会优先会采用乐观事务,只有锁冲突时,才会使用悲观事务。

使用悲观事务的语句如下:

UPDATE、DELETE、INSERT、SELECT FOR UPDATE

TiDB的悲观事务有几点需要注意:

  • SELECT FOR UPDATE语句会对已提交的最新的数据而非所修改的行加上悲观锁

  • TiDB不支持GAP锁,所以在FOR  UPDATE语句的WHERE条件使用范围条件时,还是可以插入的,比如下面的sql如果id不冲突,还是可以插入成功的:

SELECT * FROM t1 WHERE id BETWEEN 1 AND 10 FOR UPDATE;
  • 可以通过innodb_lock_wait_timeout变量设置等待锁超时时间,默认是50s

  • 不支持支持FOR UPDATE NOWAIT语法

  • 如果Point Get和Batch Point  Get算子没有读到数据,依然会对给定的主键或者唯一键加锁,阻塞其他事务对相同主键加锁或者进行写入操作

  • 在悲观事务执行期间,如果执行DDL操作,是可以成功的,但之后事务会提交失败

  • 悲观事务的执行时间有上限,默认为10分钟,可以通过参数配置

总结

业务场景的复杂化,必然导致乐观事务冲突变多,这也是TiDB后续版本转向悲观事务的重要原因。TiDB中乐观事务和悲观事务可以共存。

“如何理解TiDB的分布式事务模型”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

您可能感兴趣的文档:

--结束END--

本文标题: 如何理解TiDB的分布式事务模型

本文链接: https://www.lsjlt.com/news/61875.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何理解TiDB的分布式事务模型
    本篇内容介绍了“如何理解TiDB的分布式事务模型”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!在传统关系型...
    99+
    2024-04-02
  • 分布式事务使用Seata的AT事务模式如何理解
    分布式事务使用Seata的AT事务模式如何理解,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。项目使用了微服务,并且将一些模块进行了拆分,现在遇到了一个批量保存的场景,而且还...
    99+
    2023-06-19
  • 如何理解分布式事务
    本篇内容主要讲解“如何理解分布式事务”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何理解分布式事务”吧!事务要说分布式事务,首先...
    99+
    2024-04-02
  • 分布式事务该如何理解
    这篇文章给大家介绍分布式事务该如何理解,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。先上场景:压力测试,同时1万个买家在店铺Shang1购买东西,每个买家账户向shang1账户付钱。    &nbs...
    99+
    2023-06-02
  • 如何理解Java分布式事务
    今天小编给大家分享一下如何理解Java分布式事务的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下...
    99+
    2024-04-02
  • 如何理解分布式中的TCC模式
    这篇文章主要介绍“如何理解分布式中的TCC模式”,在日常操作中,相信很多人在如何理解分布式中的TCC模式问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何理解分布式中的TCC...
    99+
    2024-04-02
  • C#开发中如何处理分布式事务和分布式缓存
    C#开发中如何处理分布式事务和分布式缓存,需要具体代码示例摘要:在分布式系统中,事务处理和缓存管理是至关重要的两个方面。本文将介绍C#开发中如何处理分布式事务和分布式缓存,并给出具体的代码示例。引言随着软件系统的规模与复杂度增加,许多应用都...
    99+
    2023-10-22
    分布式缓存 C#开发 分布式事务处理
  • 何为分布式事务
    这篇文章主要介绍“何为分布式事务”,在日常操作中,相信很多人在何为分布式事务问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”何为分布式事务”的疑惑有所帮助!接下来,请跟着小编一...
    99+
    2024-04-02
  • 如何理解分布式Raft
    本篇内容主要讲解“如何理解分布式Raft”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何理解分布式Raft”吧!一、Raft 概述Raft 算法是分布式系统开...
    99+
    2024-04-02
  • 如何利用Redis实现分布式事务管理
    如何利用Redis实现分布式事务管理引言:随着互联网的快速发展,分布式系统的使用越来越广泛。在分布式系统中,事务管理是一项重要的挑战。传统的事务管理方式在分布式系统中难以实现,并且效率低下。而利用Redis的特性,我们可以轻松地实现分布式事...
    99+
    2023-11-07
    管理 redis 分布式事务
  • MongoDB的分布式事务怎么处理
    MongoDB支持分布式事务处理的功能,通过使用分布式事务,可以确保多个操作在各个节点上的一致性。 在MongoDB中,分布式事务是...
    99+
    2024-05-07
    MongoDB
  • 如何解决PHP开发中的分布式事务问题
    现如今,随着互联网的快速发展,越来越多的应用程序需要面临分布式事务的挑战。对于PHP开发人员来说,如何解决分布式事务是一个不可回避的问题。本文将介绍一些解决分布式事务问题的常用方法,并提供具体的代码示例。在PHP开发中,分布式事务是指在一个...
    99+
    2023-10-21
    PHP分布式事务解决方案 PHP事务管理 PHP分布式事务处理
  • 详解Java TCC分布式事务实现原理
    目录概述业务场景介绍进一步思考落地实现 TCC 分布式事务TCC 实现阶段一:TryTCC 实现阶段二:ConfirmTCC 实现阶段三:Cancel总结与思考最终一致性分布式事务如...
    99+
    2024-04-02
  • 如何理解分布式系统下基于Redis的分布式锁
    这篇文章主要介绍“如何理解分布式系统下基于Redis的分布式锁”,在日常操作中,相信很多人在如何理解分布式系统下基于Redis的分布式锁问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大...
    99+
    2024-04-02
  • 如何理解分布式锁的封装
    本篇内容主要讲解“如何理解分布式锁的封装”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何理解分布式锁的封装”吧!分布式锁通常有很多选择,基于 Redis 的,...
    99+
    2024-04-02
  • 如何理解分布式锁的场景
    本篇内容主要讲解“如何理解分布式锁的场景”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何理解分布式锁的场景”吧!秒杀场景案例对于商品秒杀的场景,我们需要防止库...
    99+
    2024-04-02
  • PHP中的分布式事务
    随着信息化时代的迅速发展,电商行业不断壮大,相应的技术也在不断地更新迭代。其中,分布式系统是当前电商行业的主流架构之一,它旨在提高系统的可用性和可扩展性。在分布式系统中,事务处理是不可避免的问题,而分布式事务又是事务处理的关键。本文将介绍P...
    99+
    2023-05-23
    PHP编程 分布式事务 事务处理
  • 如何理解C#.NET分布式锁服务
    本篇文章给大家分享的是有关如何理解C#.NET分布式锁服务,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。背  景分布式锁服务在大家的项目中或许用的不多,因为大家都把排...
    99+
    2023-06-17
  • 如何进行分布式事务框架GTS全解析
    今天就跟大家聊聊有关如何进行分布式事务框架GTS全解析,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。全局事务服务(Global Transaction Service,简称 GTS)...
    99+
    2023-06-04
  • 讲解如何利用 Python完成 Saga 分布式事务
    目录1、分布式事务2、SAGA3、SAGA 实践4、处理网络异常5、处理回滚6、小结 银行跨行转账业务是一个典型分布式事务场景,假设 A 需要跨行转账给 B,那么就涉及两个银行的数据...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作