联 系 我 们
售前咨询
售后咨询
微信关注:星环科技服务号
更多联系方式 >
6.8.6 事务控制
更新时间:7/25/2024, 11:25:02 AM

本章介绍事务处理语言。Inceptor支持的事务处理语法包括:

  • BEGIN TRANSACTION:开始事务

  • COMMIT:提交事务

  • ROLLBACK:回滚事务。

模式选择

默认情况下Inceptor会关闭Transaction Mode,要对ORC表进行事务处理,需要通过下面的开关打开ORC表对应的Transaction Mode:

SET transaction.type = inceptor;
复制

提交和回滚:COMMIT和ROLLBACK

事务处理指令为BEGIN TRANSACTION(开始事务),COMMIT(提交事务)和ROLLBACK(回滚/撤回事务)。一次事务以BEGIN TRANSACTION开始,以COMMIT或ROLLBACK结束。对ORC表的事务提交和回滚有两种方式:

  • 手动方式:使用BEGIN TRANSACTION开始一次事务,使用COMMIT提交事务,使用ROLLBACK回滚事务。

    语法

    BEGIN TRANSACTION
        <sql_statements>
        [<sql_statements>]
        ...
    COMMIT|ROLLBACK
    复制
  • 自动提交(默认方式):如果增删改指令(UPDATE, DELETE, MERGE, INSERT)没有以BEGIN TRANSACTION开始,那么Inceptor默认对所有的增删改指令都自动提交,不能回滚。

    语法

    [BEGIN TRANSACTION]
        <sql_statement>
    [COMMIT]
    [BEGIN TRANSACTION]
        <sql_statement>
    [BEGIN TRANSACTION]
    [COMMIT]
    复制

    这里,用户并不需要输入括号中的事务处理指令,Inceptor 自动执行。

Inceptor支持在事务中执行一个或多个子事务。Inceptor 提供两种执行子事务的方式:嵌套事务(Nested Transaction)和自治事务(Autonomous Transaction)。


嵌套事务

嵌套事务处理就是在一个事务里进行另一个事务。嵌套事务需要写进一个procedure中:

语法

CREATE OR REPLACE PROCEDURE pro_test() IS
BEGIN
    BEGIN TRANSACTION
        <sql_statement>
        ...
        BEGIN TRANSACTION
            <sql_statement>
            ...
        (COMMIT|ROLLBACK)
    (COMMIT|ROLLBACK)
END;
复制

在嵌套事务中,子事务与主事务互相影响。

举例

SET transaction.type=inceptor;
TRUNCATE TABLE t111;
TRUNCATE TABLE t222;
CREATE OR REPLACE PROCEDURE pro_test() IS
     BEGIN

         BEGIN TRANSACTION
             INSERT INTO t111 VALUES ('a', 1)

             BEGIN TRANSACTION
                 INSERT INTO t222 VALUES ('b', 2)
             COMMIT
         ROLLBACK
     END;
BEGIN
    pro_test()
END;
复制

上面的例子中,

BEGIN TRANSACTION
    INSERT INTO t222 VALUES ('b', 2)
COMMIT
复制

BEGIN TRANSACTION
    INSERT INTO t111 VALUES ('a', 1)
    BEGIN TRANSACTION
        INSERT INTO t222 VALUES ('b', 2)
    COMMIT
ROLLBACK
复制

的子事务。当Inceptor读到子事务中的COMMIT时,Inceptor会将该COMMIT之前所有的任务提交。也就是说,“向t111插入('a', 1)”和“向t222插入('b',2)”这两条任务都会被提交。主事务中的ROLLBACK和子事务中的COMMIT之间没有任何SQL语句,所以主事务中的ROLLBACK并不回滚任何任务。上面例子执行后,我们查看t111和t222中的记录将会得到下面的结果:

SELECT * FROM t111;
复制
value1 value2

a

1

SELECT * FROM t222;
复制
value1 value2

b

2


自治事务

自治事务提供一个在主事务中嵌套独立子事务的机制。自治事务从当前事务开始,在其自身的语境中执行。它们能独立地被提交或重新运行,而不影响正在运行的事务,也不被正在运行的事务影响。因为自治事务是与主事务相分离的,所以它不能检测到被修改过的行的当前状态。但是主事务能够检测到已经执行过的自治事务的结果。

要创建一个自治事务,您必须在匿名块的最高层或者存储过程、函数、数据包或触发的定义部分中,使用PL/SQL中的PRAGMA AUTONOMOUS_TRANSACTION语句。在这样的模块或过程中执行的SQL语句都是自治的。

语法

-- 定义一个自治事务
CREATE OR REPLACE PROCEDURE transaction_name() IS
PRAGMA AUTONOMOUS_TRANSACTION
BEGIN
    <sql_statements>
    ...
COMMIT|ROLLBACK
END;

-- 使用该自治事务
BEGIN TRANSACTION;
    <sql_statements>;
    BEGIN
    transaction_name()
    END;
COMMIT|ROLLBACK;
复制

我们使用上一节的两个事务举例,将上一节中的事务2定义为自治事务,放在事务1中:

举例

!set plsqlUseSlash true
set transaction.type=inceptor;
CREATE OR REPLACE PROCEDURE autonomous_insert() IS
PRAGMA AUTONOMOUS_TRANSACTION
BEGIN
    --子事务
    BEGIN TRANSACTION
        INSERT INTO t222 VALUES ('b', 2)
    COMMIT
END;
/

--主事务
BEGIN
BEGIN TRANSACTION
    INSERT INTO t111 VALUES ('a', 1)
    BEGIN
        autonomous_insert()
    END
ROLLBACK
END;
/
复制

在上例中,子事务中的COMMIT将只提交子事务中的任务而不对主事务有任何影响,也就是说该COMMIT只提交“向t2插入('b',2)”这一条任务。而由于主事务以ROLLBACK结束,“向t1插入('a', 1)”这一任务将被回滚。上面例子执行后,我们查看t1和t2中的记录将会得到下面的结果:

SELECT * FROM t111;
复制
value1 value2
SELECT * FROM t222;
复制
value1 value2

b

2


设置事务级别

我们提供完整的事务支持能力,用户可以通过 restful 的方式设置数据库的事务级别。

  • SerializableSnapshot,基于快照的可串行化,即 SSI

  • Serializable,基于悲观锁的可串行化

  • RepeatableRead,可以重复读

  • ReadCommitted,读提交

  • ReadUncommitted,读未提交

查看当前的事务级别
curl -X GET "<host>:<port>/bulk_transaction_isolation?[pretty]"
复制
设置事务级别
curl -X PUT "<host>:<port>/bulk_transaction_isolation?level=<isolation_level>&[timeout_s=<timeout>]"
复制

管理事务

Inceptor 支持当前锁情况的查询,以及自动分析锁等待链,提供诊断视图的能力。

下面我们提供一个功能演示:

  • 第一步:通过两个客户端分别登陆 user1 和 user2 两个用户

  • 第二步:在 user1 会话界面,执行下述 SQL 语句:

    create table acid_test(a int) stored as holodesk; -- 指定存储格式为 holodesk,当前该存储格式仅社区订阅版或其他商业版产品支持,如需选择其他存储格式,可参考 DDL 建表语句
    
    set transaction.type=holodesk;
    begin transaction;
    Batchinsert into acid_test batchvalues(
    values(1),
    values(2)
    );  --不提交事务
    复制
  • 第三步:检查加锁情况

    登录DBA Service 界面,点击【存储-事务】,检查加锁情况

    acid test1
    图 10. 可以看到 user1 加锁成功
  • 第四步: 在user2 会话界面,执行下述 SQL 语句:

    update acid_test set a = a+1 where a = 2;   --user2等锁中,等待user1事务提交才能执行成功
    复制
  • 第五步:检查锁等待链情况 登录 DBA Service 界面,点击存储-事务,查看锁等待情况

    acid test2
    图 11. 可以看到 user2 等待 user1 释放锁资源
  • 第六步:在 user1 会话界面,提交事务

    commit;  --user1事务提交成功,释放锁资源。此时user2拿锁并执行成功
    复制

此时在 DBA Service 上可以看到,user1、user2 依次提交成功并释放锁资源。