GaussDB(DWS)事务【玩转PB级数仓GaussDB(DWS)】

举报
福州司马懿 发表于 2023/02/05 13:48:30 2023/02/05
【摘要】 什么是事务 为什么需要事务 事务的执行过程 四大特性 特性的用途 语法讲解 SQL实战 虚拟场景 数据准备 恢复初始值 普通操作(正常模式) 普通操作(异常模式) 事务回滚 总结 什么是事务TRANSACTION(事务)是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。数据库事务通常包含了一个序列的对数据库的读/写操作。 为什么需要事务事务存在的目的主要有两个为数据...

什么是事务

TRANSACTION(事务)是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。数据库事务通常包含了一个序列的对数据库的读/写操作。

为什么需要事务

事务存在的目的主要有两个

  1. 为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法。
  2. 当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰。

事务的执行过程

当事务被提交给数据库管理系统(DBMS)后,DBMS 需要确保该事务中的所有操作都成功完成,并且其结果被永久保存在数据库中。如果事务中有操作没有成功完成,则事务中的所有操作都需要回滚,回到事务执行前的状态;同时,该事务对数据库或者其他事务的执行无影响,所有的事务都好像在独立的环境中运行(互不干扰和影响)。

四大特性

事务具有以下四个标准属性,通常根据首字母缩写为 ACID

  • Atomicity(原子性):一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被恢复(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
  • Consistency(一致性):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
  • Isolation(隔离性):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
  • Durability(持久性):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失

特性的用途

特性 用途
原子性 并发控制,故障恢复
隔离性 并发控制
持久性 故障恢复
一致性 SQL的完整性约束(主键约束、外键约束)

常用的并发控制技术有基于锁的并发控制和基于时间戳的并发控制,GaussDB数据库针对DDL语句采用两阶段锁技术,而针对DML语句则采用多版本控制技术(Multi-Version Concurrency Control,MVCC)。GaussDB数据库的故障恢复采用WAL日志的方式来实现,目前主要支持Redo日志,通过Redo日志和MVCC可以保证事务读写的一致性。

语法讲解

  • BEGIN: 开始一个事务,事务开始后便会一直执行下去,直到遇到 COMMIT 或 ROLLBACK 命令,不过在数据库关闭或发生错误时,事务也会自动回滚(该命令是 BEGIN TRANSACTION 命令的简写)
  • BEGIN TRANSACTION: 开始一个事务(作用同 BEGIN 命令)
  • COMMIT: 把事务调用的更改保存到数据库中,即事务提交(也可以使用 END TRANSACTION 命令)
  • END TRANSACTION: 结束并提交事务
  • ROLLBACK: 事务回滚,用于撤销尚未提交或保存到数据库的事务命令

SQL实战

虚拟场景

例子:某人要在商店使用电子货币购买100元的东西,当中至少包括两个操作:

  1. 该人账户减少 100 元
  2. 商店账户增加100元

支持事务的数据库管理系统就是要确保以上两个操作(整个"事务")都能完成,或一起取消,否则就会出现 100 元平白消失或出现的情况。

数据准备

下面创建一个简单的用户金额表

CREATE TABLE PERSON_INFO (
	NAME VARCHAR(32) PRIMARY KEY,
	MONEY INTEGER
)

图片.png

然后向表中插入数据(假设商户和购买者的账户上各有100元)

INSERT INTO PERSON_INFO (name, money) VALUES ('buyer', 100), ('shop', 100);
SELECT * FROM PERSON_INFO;

图片.png

恢复初始值

下面每个例子执行完,都要将值恢复成初始值,然后再测试下一个例子

UPDATE PERSON_INFO SET money=100

普通操作(正常模式)

现在模拟购买过程,用户先减款50元,商户再加款50元

UPDATE PERSON_INFO SET money = money-50 WHERE name IN (SELECT name FROM PERSON_INFO WHERE name = 'buyer');
UPDATE PERSON_INFO SET money = money+50 WHERE name IN (SELECT name FROM PERSON_INFO WHERE name = 'shop');
SELECT * FROM PERSON_INFO;

图片.png

普通操作(异常模式)

用户先减款50元,商户发现是假币,终止了后续交易

UPDATE PERSON_INFO SET money = money-50 WHERE name IN (SELECT name FROM PERSON_INFO WHERE name = 'buyer');
-- 发现是假币
这里直接报错,不让它继续执行即可
UPDATE PERSON_INFO SET money = money+50 WHERE name IN (SELECT name FROM PERSON_INFO WHERE name = 'shop');
SELECT * FROM PERSON_INFO;

图片.png

DAS会提示你SQL执行过程中遇到错误,是否继续执行。我们这里为了模拟真实场景,选择“终止执行”

接着使用 SELECT * FROM PERSON_INFO 查询结果,可以发现顾客已经扣款,但商户没扣款,这里莫名其妙的顾客钱少了50(这里只是商家觉得是假币,但实际不一定是假币,有可能是真币,只是破了点脏了点)

图片.png

因此,如果没有事务,一旦SQL语句中间出现异常,整个账户系统的收支就不平衡了

事务回滚

下面,我们使用数据库事务,再来模拟一遍整个流程(注意:不要忘记执行UPDATE语句,将金额还原为初始值)

BEGIN TRANSACTION;
UPDATE PERSON_INFO SET money = money-50 WHERE name IN (SELECT name FROM PERSON_INFO WHERE name = 'buyer');
-- 发现是假币
这里直接报错,不让它继续执行即可
UPDATE PERSON_INFO SET money = money+50 WHERE name IN (SELECT name FROM PERSON_INFO WHERE name = 'shop');
END TRANSACTION;
SELECT * FROM PERSON_INFO;

这里同样遇到错误,我们还是跟之前一样,终止执行

图片.png

然后查询时报错了:ERROR: current transaction is aborted, commands ignored until end of transaction block

图片.png

意思是:当前事务被终止, 命令被忽略,直到事务结束

原因:如果同一事务中如果某次数据库操作出错了,那么当前事务中这个操作以后的所有命令都将出错。

这里由于出现错误,我们不能继续用 END TRANSACTION 对事务进行提交,只能使用回滚命令返回事务前的状态。

但是GassDB很奇怪的一点是,使用Rollback并不能执行回滚,让报错消失。只能通过关闭DAS,隔一段时间再打开的方式来解决,个人觉得,这应该是个BUG!

图片.png

另外,自动回滚的设置方法,在华为GaussDB官方文档中有提及,官网文档地址如下
https://www.bookstack.cn/read/openGauss-2.1-zh/Toolreference-客户端工具.md

图片.png

有两个重要的参数

变量 设置方法 说明
ON_ERROR_ROLLBACK \set ON_ERROR_ROLLBACK on | interactive | off 如果是on,当一个事务块里的语句产生错误的时候,这个错误将被忽略而事务继续。如果是interactive,这样的错误只是在交互的会话里忽略。如果是off(缺省),事务块里一个语句生成的错误将会回滚整个事务。on_error_rollback-on模式是通过在一个事务块的每个命令前隐含地发出一个SAVEPOINT的方式工作的,在发生错误的时候回滚到该事务块。
ON_ERROR_STOP \set ON_ERROR_STOP on | off on:命令执行错误时会立即停止,在交互模式下,gsql会立即返回已执行命令的结果。off(缺省):命令执行错误时将会跳过错误继续执行。

注意:设置只能以命令行的方式进行设置,DAS虽然在内网访问,但由于其使用的是HTTP的连接方式,因此无法使用命令行设置上述参数

总结

通过上面的学习和例子,相信你已经理解了为什么要用到事务,以及事务是如何执行的,后续的文章中,我将会更深入的讲解事务会遇到的其他问题。敬请期待!

【一起来玩转PB级数仓GaussDB(DWS),分享你的技术经验与体验心得,赢开发者大礼包!】第19期有奖征文火热进行中!
此外,在云声平台提出您的宝贵建议,标题以【云驻计划-定向征文】开头,还有机会赢取额外奖励。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。