15

我的数据库背景是 Oracle,所以我惊讶地发现 Postgres 在事务中包含模式更改——如果你开始一个,创建一个表然后回滚,表就消失了。它也适用于添加和删除列。显然这是非常好的。

我们即将对部署依赖此功能的模式增量的方式进行一些更改。在此之前,我想了解交易保证的延伸范围,但我在文档中找不到任何相关信息。我假设我只是使用了错误的搜索词——我的搜索只是转到包含“事务”、“创建”和“表”等词的大命令列表。

谁能给我一些关于 Postgres 中事务模式更改的文档或讨论的指针?(我们使用的是 8.2.13,尽管我们将在不久的将来升级。)或者只是一些关于不会包含在事务中的语句的细节?

4

5 回答 5

13

根据文档上的快速 grep,这些命令不能在事务中执行:

  • 提交准备
  • 创建数据库
  • 创建表空间
  • 丢弃
  • 删除数据库
  • 删除表空间
  • 回滚准备
  • 真空
于 2009-07-10T10:38:44.737 回答
9
  • nextval并且setval对序列的操作永远不会回滚。
  • REINDEX DATABASE
  • REINDEX SYSTEM

PostgreSQL Wiki 上有一篇关于事务性 DDL的文章

于 2009-07-10T10:51:56.553 回答
4

从 PosgreSQL 9.1 版开始,模式创建语句似乎确实是事务性的。

select * from pg_namespace where nspname = 'foo';
 nspname | nspowner | nspacl 
---------+----------+--------
(0 rows)

begin;
create schema foo;
rollback;

select * from pg_namespace where nspname = 'foo';
 nspname | nspowner | nspacl 
---------+----------+--------
(0 rows)

begin;
create schema foo;
commit;

select * from pg_namespace where nspname = 'foo';
 nspname | nspowner | nspacl 
---------+----------+--------
 foo     |       10 | NULL
(1 row)
于 2012-08-31T21:09:04.910 回答
2

两个同时运行“CREATE TABLE”的会话有点古怪:

http://postgresql.1045698.n5.nabble.com/Errors-on-CREATE-TABLE-IF-NOT-EXISTS-td5659080.html

CREATE TABLE 进行初步检查以查看是否存在名称冲突。如果是这样,它要么出错(通常),要么退出并发出通知(在 IF NOT EXISTS 情况下)。但是有一个竞争条件:一个冲突的事务可以在我们进行检查之后和我们自己创建之前创建表。

链接的线程发起者和我都在自动化测试环境中遇到了这个问题,所以这只不过是一个烦恼。(我怀疑它会影响您的架构迁移,但它可以被视为对 ddl 更改的限制)

perl -MDBI -E 'fork; fork; $d=DBI->connect("dbi:Pg:dbname=$ENV{USER}");' \
 $d->do("CREATE TABLE a (b int)")'
DBD::Pg::db do failed: ERROR:
   duplicate key value violates unique constraint "pg_type_typname_nsp_index"
DETAIL:  Key (typname, typnamespace)=(a, 2200) already exists. at -e line 1.
于 2013-09-02T07:01:47.983 回答
0

从手册,第 13.5 节(货币控制:警告):

一些 DDL 命令,目前只有 TRUNCATE 和 ALTER TABLE 的表重写形式,不是 MVCC 安全的。这意味着在截断或重写提交之后,如果并发事务使用的是在 DDL 命令提交之前拍摄的快照,则表将显示为空。这只会是在 DDL 命令开始之前没有访问相关表的事务的问题 […]

关于表重写ALTER TABLE部分提到

添加带有 DEFAULT 子句的列或更改现有列的类型将需要重写整个表 […]。作为更改现有列的类型时的例外情况,如果 USING 子句不更改列内容并且旧类型要么是二进制可强制转换为新类型,要么是新类型上的无约束域,则不需要表重写 [ ...] 添加或删除系统 oid 列也需要重写整个表。

于 2018-07-10T15:31:31.213 回答