首页 > 数据库 >数据库必知必会:TiDB(4)TiKV分布式事务

数据库必知必会:TiDB(4)TiKV分布式事务

时间:2023-02-09 15:33:03浏览次数:55  
标签:TSO 事务 必知 TiKV 列族 提交 TiDB 数据 id

(数据库必知必会:TiDB(4)TiKV分布式事务)

分布式事务

存在的问题

假设有这样一个事务:

begin:
update person set name = 'Tom' where id = 1;
update person set name = 'Jack' where id = 2;
commit;

由于数据在TiKV中是分布式存储的,那么这两条数据就有可能分布在TiKV的两个实例中,比如:id=1的记录在实例1中,id=2的记录在实例2中。当在事务执行过程中实例1上id=1的记录成功更新,而此时实例2出现故障导致id=2的记录更新失败,那么以上这个简单的事务的原子性就会遭到破坏。

Percolator事务模型

TiDB采用Google Percolator事务模型来解决分布式事务的问题。

Google Percolator事务模型

Percolator事务分为两个阶段:预写(Pre-write)和提交(Commit),本质上相当于一个加强的2PC。

事务的过程

假设有这样一个事务:

begin:
update person set name = 'Frank' where id = 3;
commit;

事务开始

在事务开始时,begin时,TiDB会从PD中获取事务开始的时间戳TSO,假设TSO=100。

修改数据

然后TiDB将需要修改的数据读取到内存中,在内存中完成数据的修改。

TiDB在内存中修改数据的时候,不会将锁信息写入TiKV,此时其他会话无法感知锁的存在,是乐观事务。

乐观事务与悲观事务

乐观事务模型就是直接提交,遇到冲突就回滚。

悲观事务模型就是在真正提交事务前,先尝试对需要修改的资源上锁,只有在确保事务一定能够执行成功后,才开始提交。

对于乐观事务模型来说,比较适合冲突率不高的场景,因为直接提交大概率会成功,冲突是小概率事件,但是一旦遇到事务冲突,回滚的代价会比较大。

悲观事务的好处是对于冲突率高的场景,提前上锁的代价小于事后回滚的代价,而且还能以比较低的代价解决多个并发事务互相冲突导致谁也成功不了的场景。不过悲观事务在冲突率不高的场景并没有乐观事务处理高效。

事务提交

在commit的时候进入两阶段提交。

预写

在第一阶段,TiDB会写三个列族到TiKV中:

  • Default列族:记录带有事务开始时间戳标记(100)的修改后的数据
  • Lock列族:记录锁信息,在第一行数据加写锁(W),这是一把主锁(pk),并且记录下其他相关的信息
  • Write列族:预留用来存放提交信息

image-20230130231442240

此时,其他会话会感知到写锁的存在,其他会话不会进行id=3的数据的读、写操作。

注意:

当用户写入的数据长度小于255字节时,数据会被存储在Write列族;

当用户写入的数据长度大于255字节时,数据会被存储在Default列族。

提交

在第二阶段,TiDB会从PD中获取事务提交的时间戳TSO,假设TSO=110。

TiDB在Write列族中写入提交信息,包括事务提交的时间戳(110)和事务开始的时间戳(100),完成后在Lock列族中记录一条锁清理的数据,表示写锁已经被释放。

image-20230130232020539

此时,其他会话可进行id=3的数据的读、写操作。

TiDB如何处理分布式事务

假设有这样一个事务:

begin:
update person set name = 'Jack' where id = 1;
update person set name = 'Candy' where id = 2;
commit;

并且两条数据分布在TiKV中的两个实例上。

TiDB会按照事务的处理过程进行处理。

在预写阶段,在事务中的第一条数据(节点1,id=1)上加主锁(pk),在节点2上记录的是附加锁(@1)表示的是主锁在id=1的那条记录那里。

此时,节点1和节点2上都有写锁,其他会话不能对这些数据进行读、写操作。

在提交阶段,节点1和节点2都写入提交信息和清理写锁。

image-20230130233513685

当节点1提交成功,节点2提交失败,那么节点2上的写锁不会被清除。后续在读取数据的时候,发现有写锁存在,并且是附加锁(@1),此时需要判断事务是否提交,会根据附加锁的指向找到主锁,发现主锁已成功提交,则可判断自己在提交阶段出现了问题。因为主锁是成功提交的,所以附加锁这里只需要补充提交即可,继续写入提交信息,清理附加锁,Default列族中的数据变成最终数据。

MVCC

从前面的过程中知道,事务已预写、未提交的时候,数据不能进行读、写操作,这有一个问题,就是读也会被阻塞。

MVCC的引入是为了解决读操作被阻塞的,因为在修改中的、还未提交的数据,还不确定最后是否提交,那么读取修改前的数据应该是被允许的。

MVCC机制下,读操作按最近一次提交记录读取,无需关心锁信息,写操作需要先检查当前是否已存在其他写锁。

假设有两个事务:

--事务1
begin (start_ts = 100)
update person set name = 'Jack' where id = 1;
update person set name = 'Candy' where id = 2;
commit; (commit_ts = 110)

--事务2
begin (start_ts = 115)
update person set name = 'Tim' where id = 1;
update person set name = 'Jerry' where id = 4;

此时,事务1已成功提交,事务2未提交。

假设在时间戳TSO=120的时候,有会话读取数据:

select * from person where id in (1,2,4);

此时id=1和id=4的记录有锁信息但无提交信息,属于在事务中的数据,如果阻塞读操作,那么此时id=1和id=4的记录都是无法读取的。

image-20230131002622520

引入MVCC后。

读id=1的数据时,从Write列族中发现最近一次提交是TSO=100,读操作可以读取TSO=100的数据。

写id=1的数据时,当前锁是TSO=115,因为TSO=115的锁还未提交,所以写被阻塞。

image-20230131002842873

读id=2的数据时,从Write列族中发现最近一次提交是TSO=100,读操作可以读取TSO=100的数据。

写id=2的数据时,当前无锁,所以可以写。

image-20230131003327113

读id=4的数据时,从Write列族中发现最近一次提交是TSO=80,读操作可以读取TSO=80的数据。

写id=4的数据时,当前锁是TSO=115的附加锁,因为主锁还未提交,所以附加锁也还在事务中,写被阻塞。

image-20230131003658425

标签:TSO,事务,必知,TiKV,列族,提交,TiDB,数据,id
From: https://blog.51cto.com/u_15943369/6045906

相关文章

  • TiDB增强型 StatefulSet 控制器--Advanced StatefulSet
    K8S内置的 ​​StatefulSet​​ 为Pods分配连续的序号。比如3个副本时,Pods分别为pod-0,pod-1,pod-2。扩缩容时,必须在尾部增加或删除Pods。比如扩容到4个副本时......
  • TiDB Operator配置TiDB集群故障自动转移
    TiDB集群包括PD、TiKV、TiDB、TiFlash、TiCDC和Pump六个组件。目前TiCDC和Pump并不支持故障自动转移,PD、TiKV、TiDB和TiFlash的故障转移策略会有所不同。PD故障......
  • 必知必会的设计原则——依赖倒置原则
    概述开放封闭原则是面向对象的设计的中级目标,而依赖倒置原则是实现开放封闭原则的基础。如果开放封闭原则是设计大楼的蓝田,那么依赖倒置原则就是大楼的钢铁架构。高层模......
  • 大数据必知必会:Zookeeper(3)集群环境安装
    摘要】Zookeeper3.8.0集群环境安装安装前准备集群环境下,至少需要3台服务器。IP地址主机名称10.0.0.5node110.0.0.6node210.0.0.7node3需要保......
  • MySql查询性能优化必知必会
    作为一个写业务代码的"JAVACURDBOY",具备写出高效率SQL让应用高性能访问数据库的能力非常重要。获得这个能力的过程我收获了点知识和经验,今天在这里分享出来,希望大家多多......
  • 必知必会的设计原则——开放封闭原则
    概述开放封闭原则是面向对象所有原则的核心。对功能扩展开放,面向修改代码封闭。需求改变时,在小改变软件实体源代码(类、接口、方法等)的前提下通过扩展功能使其满足新的需......
  • K8S下TiDB集群基础环境配置
    软件版本要求软件名称版本DockerDockerCE18.09.6Kubernetesv1.12.5+CentOSCentOS7.6,内核要求为3.10.0-957或之后版本Helmv3.0.0+防火墙配置建议关闭防火墙systemctlst......
  • 数据库必知必会:TiDB(1)数据库架构概述
    (数据库必知必会:TiDB(1)数据库架构概述)TiDB体系架构TiDB兼容MySQL5.7协议,支持水平扩容或者缩容的金融级高可用的云原生分布式数据库。TiDB的体系架构为:TiDBServer,接收......
  • 必知必会的设计原则——单一职责原则
    概述单一职责原则是最简单的面向对象设计原则!定义为不要存在多于一个导致类变更的原因。通俗的说,即一个类只负责一项职责。说文字比较干巴巴,我们通过上代码来展示案例;未......
  • mysql必知必会——GROUP BY和HAVING
    GROUPBY语法可以根据给定数据列的每个成员对查询结果进行分组统计,最终得到一个分组汇总表。select子句中的列名必须为分组列或列函数,列函数对于groupby子句定义的每个组......