暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

GaussDB 事务 —— 从入门到精通

高斯精选 2023-04-28
1418

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

为什么需要事务
事务存在的目的主要有两个

为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法。

当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰。

事务的执行过程
当事务被提交给数据库管理系统(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元的东西,当中至少包括两个操作:

该人账户减少 100 元

商店账户增加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;

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

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论