BEGIN

说明

开始一个事务

语法

begin ::=

参数

WORK

表示开始一个事务。此参数没有意义。

TRANSACTION

表示开始一个事务。此参数没有意义。

READ ONLY

表示开始的事务只读。

READ WRITE

表示开始的事务可读写。

注解

如果当前已经在一个事务中了,语句 BEGIN; 将导致出错。

当没有申明 READ ONLY 和 READ WRITE 时,在不同的情况下采取不同的默认值:当数据库只读、或当前 session 只读、或当前 session 的隔离级别为 READ UNCOMMITTED 时,开始的事务将是只读的。否则开始的时候就是可读写的。

如果数据库只读、或当前session 只读、或当前 session 的隔离级别为 READ UNCOMMITTED 时,申明 READ WRITE 则导致出错,开始事务失败。

当开始一个事务之后,执行其他语句之前,可以使用 SET TRANSACTION 语句设置事务的读写属性和隔离级别。一旦执行过其他 DML 或 DDL 语句,表示事务被激活,再次使用 SET TRANSACTION 设置事务属性将失败。

当 AUTOCOMMIT 配置参数为 FALSE 时,执行一条 DML 或 DDL 或 SET TRANSACTION 语句之后,将自动进入一个事务。这相当于在这条语句之前输入了一条 BEGIN; 语句。参见 SET AUTOCOMMIT 。

若DDLCOMMITBEHAVIOR配置参数为0,且当前位于显性事务中,DDL语句执行将会自动提交先前事务,通过单独事务完成DDL操作,并最后自动开启新的事务。即显性事务中DDL操作分三个过程:COMMIT、DDL、BEGIN,且最终事务不继承原有事务的属性。

当开始只读事务时,事务将不能对数据库产生写操作,否则就出错。但若DDL自动提交功能开启,内部新开的独立事务可以成功执行,即用户的只读事务可以发生写操作。 参见下文示例2、示例3。

示例

示例1: 开始一个事务

--  清理环境
DROP TABLE tab1 CASCADE;

--  创建表并插入数据
CREATE TABLE tab1 (a INT);

INSERT INTO tab1 VALUES(1);
INSERT INTO tab1 VALUES(2);


SELECT * FROM tab1 ORDER BY a;
A(int)      |
------------
1           |
------------
2           |
总数目:2


--  开始一个事务
BEGIN;

--  事务中插入一条数据
INSERT INTO tab1 VALUES(3);


SELECT * FROM tab1 ORDER BY a;
A(int)      |
------------
1           |
------------
2           |
------------
3           |
总数目:3

--  回滚事务, 事务中插入的数据不存在了
ROLLBACK;


SELECT * FROM tab1 ORDER BY a;
A(int)      |
------------
1           |
------------
2           |
总数目:2

--  删除表
DROP TABLE tab1;

示例2: 开始一个只读事务, 执行写数据操作

--  清理环境
DROP TABLE tab2 CASCADE;

--  创建表并插入数据
CREATE TABLE tab2 (a INT);

INSERT INTO tab2 VALUES(1);
INSERT INTO tab2 VALUES(2);


SELECT * FROM tab2 ORDER BY a;
A(int)      |
------------
1           |
------------
2           |
总数目:2


--  开始一个只读事务
BEGIN READ ONLY;

--  只读事务中插入数据失败
INSERT INTO tab2 VALUES(3);
ERROR, 事务只读,该语句出错(INSERT INTO tab2 VALUES(3))



SELECT * FROM tab2 ORDER BY a;
A(int)      |
------------
1           |
------------
2           |
总数目:2

--  提交事务(结束事务)
COMMIT;

--  删除表
DROP TABLE tab2;

示例3: 开始一个只读事务, 执行 DDL 操作

--  清理环境
DROP TABLE tab3 CASCADE;

--  设置 DDL 自动提交
set DDLCOMMITBEHAVIOR = 0;

--  表 tab3 不存在, 查询报错
SELECT * FROM tab3;
ERROR, Relation "TAB3" does not exist



--  开始一个只读事务
BEGIN READ ONLY;

--  执行 DDL 语句
CREATE TABLE tab3 (a INT);

--  DDL 自动提交, 可以执行写数据操作了
INSERT INTO tab3 VALUES(1);


SELECT * FROM tab3 ORDER BY a;
A(int)      |
------------
1           |
总数目:1

--  回滚事务
ROLLBACK;



--  由于设置 DDL 自动提交
--  导致 tab3 表已存在, 回滚后没有数据
SELECT * FROM tab3 ORDER BY a;
A(int)      |
总数目:0


--  删除表
DROP TABLE tab3;


--  设置 DDL 非自动提交
set DDLCOMMITBEHAVIOR = 1;


--  表 tab3 不存在, 查询报错
SELECT * FROM tab3;
ERROR, Relation "TAB3" does not exist



--  开始一个只读事务
BEGIN READ ONLY;

--  执行 DDL 语句
CREATE TABLE tab3 (a INT);
ERROR, 事务只读,该语句出错(CREATE TABLE tab3 (a INT))


SELECT * FROM tab3 ORDER BY a;
ERROR, Relation "TAB3" does not exist


--  回滚事务
ROLLBACK;


--  由于设置 DDL 非自动提交
--  导致回滚后 tab3 表不存在, 查询报错
SELECT * FROM tab3 ORDER BY a;
ERROR, Relation "TAB3" does not exist



--  重置参数
reset DDLCOMMITBEHAVIOR;

示例4: 开始事务之后设置其属性

--  清理环境
DROP TABLE tab4 CASCADE;

--  创建表并插入数据
CREATE TABLE tab4 (a INT);

INSERT INTO tab4 VALUES(1);
INSERT INTO tab4 VALUES(2);


SELECT * FROM tab4 ORDER BY a;
A(int)      |
------------
1           |
------------
2           |
总数目:2


--  开始一个事务
BEGIN;

--  设置该事务只读
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

--  只读事务中插入数据失败
INSERT INTO tab4 VALUES(3);
ERROR, 事务只读,该语句出错(INSERT INTO tab4 VALUES(3))


--  回滚事务
ROLLBACK;

--  删除表
DROP TABLE tab4;