我想将列从timestamp
(无时区)迁移到timestamptz
类型。
我在Postgres 9.3.9。
我需要知道这个操作是否会导致表重写(锁定表),因为我的表很大并且数据库是实时的。
中找到了这个增加varchar或varbit列的长度限制,或者完全删除限制,不再需要重写表。同样,增加数字列的允许精度,或将列从受约束数字更改为无约束数字,不再需要重写表。在涉及interval,timestamp和timestamptz类型的类似情况下,也避免了表重写。
这听起来很有希望,但实际上并没有详细说明类似案例'可能是。
如果此操作 要锁定表格,我会感谢有关如何在不中断服务的情况下在实时数据库上解决此问题的建议。
答案 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';
在这种情况下,请确保使用 时区名称 ,不是简单的偏移量,也不是缩写。详细说明:
ALTER TABLE
更改现有表的定义。有 下面描述了几个子形式。请注意,需要锁定级别 每个子表单可能不同。除非举行ACCESS EXCLUSIVE
锁定 明确指出。
ALTER column_name TYPE data_type
需要 ACCESS EXCLUSIVE
锁定。虽然timestamp
和timestamptz
的内部存储格式相同,但内部值通常会被转换更改(取决于时区设置)会议!)。 Postgres必须在表格中编写每一行的新版本,因此这需要表格重写。由于操作采用了 ACCESS EXCLUSIVE
锁定,因此无需保留旧的行版本,转换后您将看不到任何死元组。
SQL Fiddle演示了时区设置对转化的作用。我还添加了一个将varchar
转换为text
的示例,其中不需要重写表格 - 除非您移动到较短的长度修改器。
注意我如何将输出转换为text
(ts_col::text
)以使sqlfiddle中的JDBC层不再添加更多(通常不需要的!)表示魔法。
在您的交易开始后尝试访问该表的并发交易将 等待 ,直到此交易完成为止。
你可以尝试通过在后台准备一个新表来保持锁定时间短,删除旧表并重命名新表,但这会使并发事务失败并出现如下错误:< / p>
错误:无法与OID 123456打开关系
详细说明:
timestamp
/ timestamptz
赞varchar
或numeric
timestamp
, time
and interval
types允许修饰符。例如,时间戳最多可存储6位数,每个默认值为小数秒,但您可以修改:timestamp(0)
不存储小数秒。
varchar(10)
的转换 - &gt; varchar(20)
不需要重写表,因为源类型中的值也保证在目标类型中适合(二进制兼容)。
timestamp (0)
- &gt;也是如此。 timestamp
或timestamptz(3)
- &gt; timestamptz(5)
。这是手册在quoted passage in the release notes中所指的内容:
在涉及的类似案例中也避免了表格重写
interval
,timestamp
和timestamptz
类型。