【我和 openGauss 的故事】 openGauss 5.0.0 事务相关语法
秋秋 [openGauss](javascript:void(0);) 2023-08-03 16:49 发表于四川
众所周知, openGauss 是一款开源关系型数据库管理系统,采用木兰宽松许可证 v2 发行,是 PostgreSQL 9.2.4 版本的硬分叉,经历 HUAWEI 多年的孵化,并已历经了两个 LTS 版本。
现在的 openGauss 5.0.0 正是第三个 LTS 版本,发行于 3 月 31 日,版本生命周期为三年。
openGauss 5.0.0 是流行的开源关系型数据库管理系统,它支持事务处理,下面我们来看看。
事务隔离级别
在 openGauss 5.0.0 中,支持 READ COMMITTED (读已提交)和 REPEATABLE READ (可重复读) 两种事务隔离级别。默认隔离级别是 READ COMMITTED (读已提交),保证不会读到脏数据。当事务使用此隔离级别时,SELECT 查询(没有 FOR UPDATE/SHARE 子句)只能看到在查询开始之前提交的数据;它不会看到未提交的数据,也不会看到并发事务在查询执行期间提交的更改。事务可重复读隔离级别,事务只能读到事务开始之前已提交的数据,不能读到未提交的数据以及事务执行期间其它并发事务提交的修改(但是,查询能查看到自身所在事务中先前更新的执行结果,即使先前更新尚未提交)。这个级别和读已提交是不一样的,因为可重复读事务中的查询看到的是事务开始时的快照,不是该事务内部当前查询开始时的快照,就是说,单个事务内部的 select 命令总是查看到同样的数据,查看不到自身事务开始之后其他并发事务修改后提交的数据。使用该级别的应用必须准备好重试事务,因为可能会发生串行化失败。在 openGauss 中,目前功能上不支持 SERIALIZABLE 隔离级别,等价于 REPEATABLE READ。
此外,在 openGauss 5.0.0 中,使用 全局事务管理器(Global Transaction Manager, GTM)来管理事务,GTM 负责全局事务号的分发,事务提交时间戳的分发以及全局事务运行状态的登记。
事务管理命令
在 openGauss 5.0.0 中,可以使用以下命令来启动和提交事务:
使用 BEGIN 语句
openGauss 的语法为:
BEGIN [ WORK | TRANSACTION ] [ { ISOLATION LEVEL { READ COMMITTED | SERIALIZABLE | REPEATABLE READ } | { READ WRITE | READ ONLY } } [, ...] ];
复制代码
演示实例:
begin work isolation level repeatable read read only;
复制代码
使用 START 语句
openGauss 的语法为:
START TRANSACTION [ { ISOLATION LEVEL { READ COMMITTED | SERIALIZABLE | REPEATABLE READ } | { READ WRITE | READ ONLY } } [, ...] ];
复制代码
演示实例:
START TRANSACTION isolation level repeatable read read WRITE;
复制代码
使用 SET 在事务中改变事务隔离级别
openGauss 的语法为:
{ SET [ LOCAL ] TRANSACTION|SET SESSION CHARACTERISTICS AS TRANSACTION } { ISOLATION LEVEL { READ COMMITTED | SERIALIZABLE | REPEATABLE READ } | { READ WRITE | READ ONLY } } [, ...];
复制代码
演示实例:
SET LOCAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;
复制代码
提交事务
openGauss 的语法为:
{ COMMIT | END } [ WORK | TRANSACTION ] ;
复制代码
回滚事务
当事务无法继续进行时,系统执行回滚,取消与该事务相关的所有已完成的数据库操作。
openGauss 的语法为:
ROLLBACK [ WORK | TRANSACTION ];
复制代码
openGauss 事务验证实践
隐式提交案例一则
开启一个会话,尝试在事务显示开启时退出客户端,再次登入后查看数据是否插入成功,答案是否。
`openGauss=# begin;
BEGIN
openGauss=# insert into t select 2;
INSERT 0 1
openGauss=# select * from t;
id
1
2
(2 rows)
$ gsql
gsql ((openGauss 5.0.0 build a07d57c3) compiled at 2023-03-29 03:07:56 commit 0 last mr )
Non-SSL connection (SSL connection is recommended when requiring high-security)
Type “help” for help.
openGauss=# select * from t;
id
1
(1 row)`
复制代码
说明在事务中退出客户端,当前事务并不会隐式提交。
默认事务隔离级别 RC
openGauss 中默认事务提交级别 RC,下面做一个实验加以验证。
开启两个会话,Session A 和 Session B:
`-- Session A:
openGauss=# begin;
BEGIN
openGauss=# insert into t select 3;
INSERT 0 1
openGauss=# select * from t;
id
1
3
(2 rows)
– Session B:
openGauss=# begin;
BEGIN
openGauss=# select * from t;
id
1
(1 row)`
复制代码
当前会话只能看到事务开始之前的 t 表数据。并且,Session B 无法读到未提交的数据,不存在脏读现象。
DDL 可回滚 – create table
在 openGauss 中,显式开启一个事务,然后执行 DDL 语句,那么这个 DDL 语句可以进行回滚,确认语句没有问题后,再进行显式提交。例如,在 Session A 中开启显式事务,并创建表 tr。
`-- Session A:
openGauss=# begin;
BEGIN
openGauss=# create table tr (id int);
CREATE TABLE
openGauss=# \dt
List of relations
Schema | Name | Type | Owner | Storage
--------±-----±------±------±---------------------------------
public | t | table | omm | {orientation=row,compression=no}
public | tr | table | omm | {orientation=row,compression=no}
(2 rows)
– Session B:
openGauss=# \d
List of relations
Schema | Name | Type | Owner | Storage
--------±-----±------±------±---------------------------------
public | t | table | omm | {orientation=row,compression=no}
(1 row)
– Session A:
openGauss=# rollback;
ROLLBACK
openGauss=# \dt
List of relations
Schema | Name | Type | Owner | Storage
--------±-----±------±------±---------------------------------
public | t | table | omm | {orientation=row,compression=no}
(1 row)
– Session B:
openGauss=# \d
List of relations
Schema | Name | Type | Owner | Storage
--------±-----±------±------±---------------------------------
public | t | table | omm | {orientation=row,compression=no}
(1 row)`
复制代码
DDL 可回滚 – truncate table
同样地,在 openGauss 中,truncate table 也可以回滚。例如,清空表 t 的数据:
`-- Session A:
openGauss=# select * from t;
id
1
(1 row)
openGauss=# begin;
BEGIN
openGauss=# truncate table t;
TRUNCATE TABLE
openGauss=# select * from t;
id
(0 rows)
– Session B:
$ gsql
gsql ((openGauss 5.0.0 build a07d57c3) compiled at 2023-03-29 03:07:56 commit 0 last mr )
Non-SSL connection (SSL connection is recommended when requiring high-security)
Type “help” for help.
openGauss=# select * from t;
id
1
(1 row)
openGauss=# select * from t;`
复制代码
此时, Session A 中的 truncate 操作已经执行完成,可以看到事务中表中无数据,但是,Session B 再次去查询表 t 的数据时,事务会进入等待状态,直到 Session A 发出 commit/rollback 指令。
`-- Session A:
openGauss=# rollback;
ROLLBACK
openGauss=# select * from t;
id
1
(1 row)
– Session B:
openGauss=# select * from t;
id
1
(1 row)`
复制代码
此外,由于 openGauss 引入了分布式事务,所以对于事务的处理复杂的多。
评论