OpenGauss数据库事务的执行过程

首先,在开启事务的执行流程之前,我们先来认识一下什么是事务?

事务的概念

事务(Transaction)是由一系列对系统中数据进行访问与更新的操作所组成的一个程序执行逻辑单元(Unit)。事务包括从事务开始到事务结束期间执行的所有数据库操作。

并非所有对数据库的操作序列都是数据库事务。事务应该具备四个核心属性,即ACID特性:

  • 原子性(Atomicity):指事务必须是一个原子的操作序列单元。。事务中包含的各项操作在一次执行过程中,只允许出现以下两种状态之一。
    • 全部成功执行。
    • 全部不执行。
    • 任何一项操作失败都将导致整个事务失败,同时其他已经被执行的操作都将被撤销并回滚,只打所有的操作全部成功,整个事务才算是成功完成。
  • 一致性(Consistency):事务应当确保数据库的状态从一个一致状态转变为另一个一致状态。
  • 隔离性(Isolation):在并发环境中,并发的事务是相互隔离的,一个事务的执行不能被其他事务干扰。也就是说,不同的事务并发操纵相同的数据时,每个事务都有各自完整的数据空间,即一个事务内部的操作及使用的数据对其他并发事务是隔离的,并发执行的 各个事务之间不能互相干扰。
  • 持久性(Durability):事务一旦提交,它对数据库中对应数据的状态变更就应该是永久性的。换句话说,一旦某个事务成功结束,那么它对数据库所做的更新就必须被永久保存下来——即使发生系统崩溃或机器宕机等故障,只要数据库能够重新启动,那么一定能够将其恢复到事务成功结束时的状态。

接下来让我去认识一下事务的整个执行流程,以update操作为例:

更新操作的执行流程

SQL客户端发送SQL命令

通过SQL客户端将SQL命令(update)发送到OG父线程(相当于客户端向数据库发送了一个链接请求),接下来父线程监听到了客户端连接后,会为每一个客户端连接衍生一个opengauss子线程专门处理该连接的而客户端请求。

例如发送的update语句如下:

update table table1 set col2='xxx' where id='abc';

SQL客户端与子线程连接建立

子线程对SQL客户端进行身份验证,验证通过后子线程与SQL客户端建立连接,通过网络通信来进行数据传输。

SQL查询分析阶段

词法分析,语法分析,语义分析的阶段

子线程调用OG的SQL引擎,通过SQL引擎的查询分析器接收传入的SQL命令,将其转换为内部数据结构(分析树/语法树)。接着SQL引擎的查询分析器对解析后的命令进行语义分析,验证命令的正确性,并生成相应的查询树。

相关概念介绍:

词法分析:将SQL语句解析成tokens(词法单元),一个token表示一个元素例如关键字,标识符,常量等。并传递给语法分析器。

语法分析:语法分析器将词法单元转换为语法树。

语义分析:确定语义是合法的。语义分析阶段产生查询树。

查询分析:根据客户端输入的SQL命令,通过词法分析、语法分析、语义分析将用户的SQL命令转换成查询树(Query结构)。

查询分析处理阶段分为两个:查询分析阶段(查询分析器)和查询执行阶段(查询优化器)

  • 词法分析:将输入的SQL查询字符串分解为一系列词法单元(tokens)的过程。每个词法单元代表SQL查询中的独立元素,例如关键字,标识符,运算符,常量等。词法分析器会按照预定的规则扫描输入的字符串,并将识别出的词法单元传递给语法分析器。
  • 语法分析:将词法分析得到的词法单元序列转换为抽象语法树的过程。在整个阶段,语法分析器会根据预定义的规则对词法单元进行组合,并生成一颗表示SQL查询结构的语法树。
  • 语义分析:对代码进行深层次的语义检查和解释,它主要的作用是确保程序在语义上是而合法的,并进行语义转化和语义解释,以便后续的优化和执行。语义分析的目的是检查程序语义的正确性,即确定程序是否符合变成语言的语义规则和约束,他设计对语句,表达式,类型,作用域,符合引用等进行分析和验证。具体来说语义分析会执行以下任务:
    • 类型检查:验证表达式和操作符之间的类型兼容性,确保不会出现类型错误,例如将字符串与数字相加。
    • 符号表管理:管理标识符的声明和引用,检查变量,函数等标识符的作用域,可见性和重复定义等问题。
    • 语义约束检查:检查语法规则以外的语义约束,例如数组索引必须是整数,函数调用的参数数量与声明的阐述数量匹配等。
    • 常量简化:对于常量表达式,进行计算和简化,以便在编译时进行优化。

        通过语义分析,查询分析器可以检测出源代码中的潜在错误,并确保程序在语义上是一致合法的。

查询优化阶段

SQL引擎的查询分析器将解析后的查询树传递给查询规划模块,查询规划模块会考虑表、列的统计信息、索引等,选择最优的 执行策略并生成执行计划。

在这个update 例子中,优化器会选择使用表table1的主键(即id列)来定位需要更新的行。

锁定数据库对象

PDATE命令会请求对需要更新的数据对象(表)table1加锁,以防止其他并发事务对其进行修改。如果表上有ROW EXCLUSIVE(排他锁)以上级别的锁,则会等待锁释放。

执行update操作

执行器按照update执行计划的步骤,逐步执行具体的操作。对于update命令,执行器会根据主键id('abc')和col2找到需要更新的行数据。这里update的过程会涉及到MVCC(多版本并发控制)功能。

日志记录

update操作记录(事务)写入到wal buffer(共享缓存区)的WAL日志文件中。通过walwriter线程将WAL buffer的内容刷新到磁盘并保存在xlog日志文件中,以便在发生故障时可以进行恢复。

释放锁定

数据库内核会释放之前对数据对象的锁定,允许其他事务对这些数据对象进行操作。

数据落盘&持久化

update操作完成后,数据库内核会将更新后的数据写入磁盘,确保数据的持久化。

pagewriter线程负责将脏页数据(共享缓存区的数据与磁盘的数据不一致)拷贝至双写(double-writer)文件(data/base目录下)并落盘,然后将脏页转发给bgwriter子线程进行数据下盘操作(数据下到base目录下的表文件),如果发生数据页”折断”的问题,就会从双写空间里找到完整的数据页进行恢复。bgwriter线程对pagewriter线程转过来的脏页数据持续的进行刷盘操作(持续的写入表文件),目的是让数据库线程在进行用户查询时可以很少或者几乎不等待写动作的发生,这样的机制同样也减少了检查点造成的性能下降。

结果返回SQL客户端

子线程将执行结果返回给SQL客户端,SQL客户端收到响应后,可以继续发送其他SQL命令或执行其他操作。

在客户端断开连接时释放线程

总结:

上述流程涉及解析器、分析器、访问规划器、锁管理器、查询优化器、执行计划生成器、WAL模块、存储管理器等多个模块。这些模块协同工作,保证SQL命令的正确执行,数据的一致性和持久性,并处理并发访问和故障恢复等问题。

  • 38
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值