PostgreSQL之 事务的提交与回滚

PostgreSQLpsql中,如果执行一个dml或ddl语句,没有先运行begin;的话,一执行完就马上提交了,不能回滚,这样容易导致误操作的发生,避免这个风险的办法是关闭自动提交,方法如下:

设置\set AUTOCOMMIT off

testdb=#  create table tt1(x int);
CREATE TABLE
Time: 0.593 ms
testdb=#  select * from tt1;
 x 
---
(0 rows)

testdb=#  rollback;
ROLLBACK


testdb=#  select * from tt;
ERROR:  relation "tt" does not exist
LINE 1: select * from tt;
                      ^
Time: 0.376 ms

这儿我们需要注意的是,不同于Oracle,PG的DDL事务一样是可以回滚的,并没有隐式提交的概念


testdb=#  \d       
       List of relations
 Schema | Name | Type  | Owner 
--------+------+-------+-------
 public | foo  | table | kiwi
 public | test | table | kiwi
(2 rows)

 

rollback的功能在数据库中都一样,未提交的操作都会回滚,psql中默认配置下AUTOCOMMIT是打开的,这一点和oracle不同,


如果测试需要先把autocommit设置为off

\set AUTOCOMMIT off

 

savepoint可以创建保存点,可以作为rollback的指向。

一个会话开启一个事务后,关闭事务自动提交,创建多个savepoint点,可以多次rollback到同一个savepointrollbacksavepoint后可以继续操作,参考如下:

 

创建测试表

create table tt(id int);

 

testdb=# \set AUTOCOMMIT off   #关闭自动提交

 

执行以下sql事务语句

begin;

insert into tt values(1);

insert into tt values(2);

savepoint savepoint1;

insert into tt values(3);

insert into tt values(4);

savepoint savepoint2;

insert into tt values(5);

insert into tt values(6);

 

testdb=# select * from tt;

 t1 

----

 1

 2

 3

 4

 5

 6

(6 rows)

 

testdb=# rollback to savepoint savepoint2;   #回滚到保存点savepoint2 ,查看数据

ROLLBACK

testdb=# select * from tt;

 t1 

----

 1

 2

 3

 4

(4 rows)

 

testdb=# rollback to savepoint savepoint1;  #回滚到保存点savepoint1,查看数据

 

ROLLBACK

testdb=# select * from tt;

 id

----

  1

  2

(2 rows)

 

testdb=# insert into tt values(3);

INSERT 0 1

testdb=# insert into tt values(4);

INSERT 0 1

testdb=# select * from tt;

 id

----

  1

  2

  3

  4

(4 rows)

 

2.rollbacksavepoint2后操作如果出错,后续的所有操作会报

ERROR:  current transaction is aborted, commands ignored until end of transaction block

这时候需要再次rollback to savepoint2可以回滚至savepoint2

 

testdb=# insert into tt values('dfsdfdsf','sdf');

ERROR:  INSERT has more expressions than target columns

LINE 1: insert into tt values('dfsdfdsf','sdf');

                                         ^

testdb=# select * from tt;

ERROR:  current transaction is aborted, commands ignored until end of transaction block

testdb=# \d tt

ERROR:  current transaction is aborted, commands ignored until end of transaction block

testdb=# ;

testdb=# select * from tt;

ERROR:  current transaction is aborted, commands ignored until end of transaction block

testdb=# rollback to savepoint savepoint2;

ROLLBACK

testdb=# select * from tt;

 t1 

----

 1

 2

 3

 4

(4 rows)

 

testdb=# commit;   #如果此处执行手动提交事务,再执行回滚,会报错!!

COMMIT

testdb=# select * from tt;

 id

----

  1

  2

  3

  4

(4 rows)

 

testdb=# rollback to savepoint savepoint1;   #此处是回滚失败

ERROR:  no such savepoint

STATEMENT:  rollback to savepoint savepoint1;

ERROR:  no such savepoint

 

结论:

1PG的自动提交默认是开启状态,ddl语句也可以回滚操作,这两点和oracle有区别。

2)事务的提交与回滚体现事务的原子性特征,事务语句要么提交,要么回滚;

3)事务执行过程中可以任意创建保存点,根据需要执行回滚操作,如果不指定保存点,回滚操作会回滚到事务起始点,即begin开始的地方;

4)执行回滚操作在比较大的事务中,可以把执行过程分为几个步骤,每个步骤执行完成后创建一个保存点,后续步骤执行失败时,可回滚到之前的保存点,而不必回滚整个事务。


by  波罗

你可能感兴趣的:(PostgreSQL,Highgo,DB)