事务内 PostgreSQL 模式更改的限制?

发布于 2024-07-26 04:02:31 字数 343 浏览 12 评论 0原文

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

我们即将对依赖此功能的架构增量的部署方式进行一些更改。 在我们这样做之前,我想了解交易保证的期限有多长,但我在文档中找不到任何相关信息。 我假设我只是使用了错误的搜索词 - 我的搜索只是进入包含“交易”、“创建”和“表”等词的大命令列表。

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

My database background is with Oracle, so I was surprised to discover that Postgres includes schema changes in transactions - if you begin one, create a table and then rollback, the table goes away. It works for adding and removing columns as well. Obviously this is very nice.

We're about to make some changes to the way we deploy schema deltas that rely on this feature. Before we do, I'd like to find out how far the transactional guarantee extends, but I can't find any information on it in the documentation. I assume I'm just using the wrong search terms - my searches just go to big lists of commands which include the words 'transaction', 'create' and 'table'.

Can anyone give me some pointers to docs or discussions about transactional schema changes in Postgres? (We're using 8.2.13, although we'll be upgrading in the not too distant future.) Or just some details about statement that won't be included in the transaction?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

九局 2024-08-02 04:02:34

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

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

关于表重写 ALTER TABLE 部分提到

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

From the manual, section 13.5 (Currency Control: Caveats):

Some DDL commands, currently only TRUNCATE and the table-rewriting
forms of ALTER TABLE, are not MVCC-safe. This means that after the
truncation or rewrite commits, the table will appear empty to
concurrent transactions, if they are using a snapshot taken before the
DDL command committed. This will only be an issue for a transaction
that did not access the table in question before the DDL command
started […]

Regarding table rewriting the ALTER TABLE section mentions

Adding a column with a DEFAULT clause or changing the type of an
existing column will require the entire table […] to be
rewritten. As an exception when changing the type of an existing
column, if the USING clause does not change the column contents and
the old type is either binary coercible to the new type or an
unconstrained domain over the new type, a table rewrite is not needed […] Adding
or removing a system oid column also requires rewriting the entire
table.

浅听莫相离 2024-08-02 04:02:33

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

  • cluster
  • commit准备
  • 创建数据库
  • 创建表空间
  • 丢弃
  • 删除数据库
  • 删除表空间
  • 回滚准备
  • 真空

According to quick grep on docs, these commands cannot be executed in transactions:

  • cluster
  • commit prepared
  • create database
  • create tablespace
  • discard
  • drop database
  • drop tablespace
  • rollback prepared
  • vacuum
当梦初醒 2024-08-02 04:02:33
  • 对序列的 nextvalsetval 操作永远不会回滚。
  • REINDEX DATABASE
  • REINDEX SYSTEM

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

  • nextval and setval operations on sequences are never rolled back.
  • REINDEX DATABASE
  • REINDEX SYSTEM

There's an article about transactional DDL on the PostgreSQL Wiki

丶情人眼里出诗心の 2024-08-02 04:02:33

从 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)

As of version 9.1 of PosgreSQL, it appears that schema create statements are indeed transactional.

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)
梦里泪两行 2024-08-02 04:02:33

两个会话同时运行“CREATE TABLE”有点活泼:

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

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

链接的线程启动器和我在自动化测试环境中都遇到了这个问题,
所以这只不过是一个烦恼而已。 (我怀疑这会影响你的模式迁移,但它可以被视为对 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.

Two sessions concurrently running "CREATE TABLE" is a little racy:

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

CREATE TABLE does a preliminary check to see whether a name conflict
exists. If so, it either errors out (normally) or exits with a notice
(in the IF NOT EXISTS case). But there's a race condition: a
conflicting transaction can create the table after we make that check
and before we create it ourselves.

Both the linked thread initiator and I hit this in automated testing environments,
so it's not much more than an annoyance there. (I doubt it would effect your schema migrations, but it can be seen as a limit on ddl changes)

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.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文