Postgresql 将列从timestamp更改为timestamp会锁定表吗?
我想将列从Postgresql 将列从timestamp更改为timestamp会锁定表吗?,postgresql,concurrency,timestamp,postgresql-9.3,alter-table,Postgresql,Concurrency,Timestamp,Postgresql 9.3,Alter Table,我想将列从时间戳(无时区)迁移到时间戳类型 我在读博士后9.3.9 我需要知道这个操作是否会导致表重写(锁定表),因为我的表很大,数据库是活动的 我在以下文件中发现: 增加varchar或varbit列的长度限制,或完全删除该限制,不再需要重写表。类似地,增加数值列的允许精度,或将列从受约束的数值更改为无约束的数值,不再需要重写表。在涉及间隔、时间戳和时间戳类型的类似情况下,也可以避免表重写 这听起来很有希望,但实际上并没有详细说明“类似案例”可能是什么 如果此操作要锁定表,我希望您能建议如何在
时间戳
(无时区)迁移到时间戳
类型
我在读博士后9.3.9
我需要知道这个操作是否会导致表重写(锁定表),因为我的表很大,数据库是活动的
我在以下文件中发现:
增加varchar或varbit列的长度限制,或完全删除该限制,不再需要重写表。类似地,增加数值列的允许精度,或将列从受约束的数值更改为无约束的数值,不再需要重写表。在涉及间隔、时间戳和时间戳类型的类似情况下,也可以避免表重写
这听起来很有希望,但实际上并没有详细说明“类似案例”可能是什么
如果此操作要锁定表,我希望您能建议如何在不中断服务的情况下在实时数据库上解决此问题。首先,您似乎混淆了锁定和表重写。发行说明中的说明谈到了表格重写——它总是在表格上占据一席之地。但这里有许多其他操作也需要锁 您需要:
ALTER TABLE tbl ALTER ts_col TYPE timestamptz;
除非您要在转换中设置特定时区,而不是会话的当前时区:
ALTER TABLE tbl ALTER ts_col TYPE timestamptz USING ts_col AT TIME ZONE 'Europe/London';
在这种情况下,请确保使用时区名称,而不是简单的偏移量或缩写。详情:
altertable
更改现有表的定义。有
下面介绍了几个子窗体。请注意,锁定级别是必需的
每个子窗体可能不同。除非另有说明,否则将保持访问独占
锁
明确指出
ALTER column\u name TYPE data\u TYPE
采用这样的访问独占
锁。虽然时间戳
和时间戳
的内部存储格式相同,但内部值通常会通过转换进行更改(取决于会话的时区设置!)。Postgres必须为表中的每一行编写一个新版本,因此这也需要重写表。由于操作采用了独占访问锁,因此无需保留旧的行版本,并且在转换后不会看到死元组
演示时区设置在转换中的作用。我还添加了一个将varchar
转换为text
的示例,该示例不需要重写表-除非移动到较短的长度修饰符。注意我是如何将输出转换为
text
(ts_col::text
)的,以防止SQLFIDLE中的JDBC层添加更多(通常是不需要的!)表示法
在事务开始后尝试访问表的并发事务将等待,直到该事务完成
您可以尝试通过在后台准备一个新表、删除旧表并重命名新表来缩短锁定时间,但这会导致并发事务失败,并出现如下错误:
错误:无法打开与OID 123456的关系
详情:
时间戳
/时间戳
如varchar
或numeric
允许修饰符。例如,时间戳在默认情况下最多可存储6位小数秒,但您可以修改:timestamp(0)
不存储小数秒
从varchar(10)
->varchar(20)
转换不需要重写表,因为源类型中的值也保证适合(二进制兼容)目标类型
时间戳(0)
->时间戳
或时间戳(3)
->时间戳(5)
。这就是手册中提到的:
在涉及
间隔
、时间戳
和时间戳
类型
所以如果我做了
设置本地时区class='UTC'代码>更改列之前,存储的值将保持不变。。。我现在意识到我的问题是:在这种特殊情况下,它仍然会导致表重写吗?@Anentropic:是的,设置timezone='UTC'
会导致相同的内部值。由于转换后的数据类型是timestamptz
,因此文本表示形式会发生变化,并且取决于当前的时区设置。我是否应该从您的sql FIDLE中了解到,由于xmin
值发生了变化,即使本地值为UTC,存储值也保持不变,行数据仍然被重写?因此,在所有情况下,更改列类型都可能导致表重写?@Anentropic:Yes。博士后不会挑选一个特例。我终于成功地在fiddle中添加了另一个演示(站点似乎过载)。一个varchar
->text
转换,您可以看到xmin
没有改变。varchar(10)
->varchar(20)
。但是对于varchar(20)
->varchar(10)
它会发生变化(值可能会被截断)。@Anentropic:我又增加了一章来说明手册中有关段落的子项。