将列从时间戳更改为时间戳会锁定表吗?

Ane*_*pic 3 postgresql concurrency timestamp alter-table postgresql-9.3

我想将一列从timestamp(无时区)迁移到timestamptz类型。

我在 Postgres 9.3.9 上。

我需要知道此操作是否会导致表重写(锁定表),因为我的表很大并且数据库处于活动状态。

我在9.2 发行说明中发现了这一点:

增加 varchar 或 varbit 列的长度限制,或完全删除限制,不再需要重写表。同样,增加数值列的允许精度,或将列从受约束的数值更改为不受约束的数值,不再需要重写表。在涉及间隔、时间戳和时间戳记类型的类似情况下,也可以避免表重写。

这听起来很有希望,但实际上并没有详细说明“类似案例”可能是什么。

如果此操作要锁住我会很感激了如何解决这个在实时数据库在不中断服务的建议表。

Erw*_*ter 6

首先,您似乎混淆了锁和表重写。发行说明中的​​注释谈到了表重写——它总是对表进行ACCESS EXCLUSIVE锁定。但是这里还有许多其他操作也需要锁定。

你需要:

ALTER TABLE tbl ALTER ts_col TYPE timestamptz;
Run Code Online (Sandbox Code Playgroud)

除非您想在转换中设置特定时区,而不是会话的当前时区:

ALTER TABLE tbl ALTER ts_col TYPE timestamptz USING ts_col AT TIME ZONE 'Europe/London';
Run Code Online (Sandbox Code Playgroud)

在这种情况下,请务必使用时区名称而不是简单的偏移量或缩写。细节:

文档:

ALTER TABLE更改现有表的定义。下面描述了几个子表单。请注意,每个子表单所需的锁定级别可能不同。一个ACCESS EXCLUSIVE锁举行,除非明确指出。

ALTER column_name TYPE data_type需要这样的ACCESS EXCLUSIVE。而内部存储格式timestamptimestamptz是相同的,内部通常由转换改变(取决于会话的时区设置!)。Postgres 必须为表中的每一行编写一个新版本,因此这也需要对表进行重写。由于操作需要ACCESS EXCLUSIVE锁定,因此无需保留旧的行版本,转换后您将看不到死元组。

SQL Fiddle演示了时区设置对转换的作用。我还添加了一个例子转换varchartext,这并没有要求表重写-除非你移动到更短的长度修正。
请注意我如何将输出转换为text( ts_col::text) 以防止 sqlfiddle 中的 JDBC 层添加更多(通常不需要!)表示魔法。

在您的事务开始后尝试访问该表的并发事务将等到该事务完成。

可以尝试通过在后台准备一个新表来缩短锁定时间,删除旧表并重命名新表,但这会使并发事务失败并出现如下错误:

错误:无法打开与 OID 123456 的关系

细节:

“类似案例”为timestamp/timestamptz

varcharnumeric timestamptimeinterval类型允许修饰符。例如,时间戳默认为小数秒存储最多 6 位数字,但您可以修改:timestamp(0)不存储小数秒。

varchar(10)->的转换varchar(20)不需要重写表,因为源类型中的值也保证适合(二进制兼容)目标类型。

timestamp (0)->timestamptimestamptz(3)->也是如此timestamptz(5)。这就是手册在发行说明中引用的段落中所指的内容:

表重写也避免了在涉及类似案件 intervaltimestamp以及timestamptz类型。