将时间戳更改为timestamptz是否会锁定表格?

时间:2015-09-09 13:19:34

标签: postgresql concurrency timestamp postgresql-9.3 alter-table

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

我在Postgres 9.3.9。

我需要知道这个操作是否会导致表重写(锁定表),因为我的表很大并且数据库是实时的。

我在9.2 release notes

中找到了这个
  

增加varchar或varbit列的长度限制,或者完全删除限制,不再需要重写表。同样,增加数字列的允许精度,或将列从受约束数字更改为无约束数字,不再需要重写表。在涉及interval,timestamp和timestamptz类型的类似情况下,也避免了表重写。

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

如果此操作 要锁定表格,我会感谢有关如何在不中断服务的情况下在实时数据库上解决此问题的建议。

1 个答案:

答案 0 :(得分:4)

首先,你似乎在混淆锁和表重写。发行说明中的​​说明讨论了 表重写 - 总是在表上采用ACCESS EXCLUSIVE lock。但是这里有许多其他操作也会锁定。

你需要:

ALTER TABLE tbl ALTER ts_col TYPE timestamptz;

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

ALTER TABLE tbl ALTER ts_col TYPE timestamptz USING ts_col AT TIME ZONE 'Europe/London';

在这种情况下,请确保使用 时区名称 是简单的偏移量,也不是缩写。详细说明:

The documentation:

  

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

ALTER column_name TYPE data_type需要 ACCESS EXCLUSIVE锁定。虽然timestamptimestamptz的内部存储格式相同,但内部通常会被转换更改(取决于时区设置)会议!)。 Postgres必须在表格中编写每一行的新版本,因此这需要表格重写。由于操作采用了 ACCESS EXCLUSIVE锁定,因此无需保留旧的行版本,转换后您将看不到任何死元组。

SQL Fiddle演示了时区设置对转化的作用。我还添加了一个将varchar转换为text的示例,其中需要重写表格 - 除非您移动到较短的长度修改器。
注意我如何将输出转换为textts_col::text)以使sqlfiddle中的JDBC层不再添加更多(通常不需要的!)表示魔法。

在您的交易开始后尝试访问该表的并发交易将 等待 ,直到此交易完成为止。

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

  

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

详细说明:

&#34;类似案例&#34; timestamp / timestamptz

varcharnumeric timestamp, time and interval types允许修饰符。例如,时间戳最多可存储6位数,每个默认值为小数秒,但您可以修改:timestamp(0)不存储小数秒。

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

timestamp (0) - &gt;也是如此。 timestamptimestamptz(3) - &gt; timestamptz(5)。这是手册在quoted passage in the release notes中所指的内容:

  

在涉及的类似案例中也避免了表格重写   intervaltimestamptimestamptz类型。