Neu*_*onQ 27 mysql postgresql alter-table
大多数“流行”(MySQL、Postgres...)数据库系统如何处理实时生产数据库上的表更改(例如添加、删除或更改列的类型)?
我知道正确的方法是备份所有计划停机时间,然后进行更改。
但是......当前的数据库系统是否支持在不停止任何事情的情况下“在线”执行这些操作?(也许只是延迟引用刚刚更改/删除的列的查询)
当我只是ALTER TABLE...在实时运行的数据库上执行操作时会发生什么?当这种情况发生时,一切都会停止吗?数据会损坏吗?等等。
同样,我主要指的是 Postgres 或 MySQL,因为这些是我遇到的。
(而且,是的,在我以“正确的方式”做之前,任何时候我必须这样做,备份事情,安排停机等......但我只想知道是否有可能“快速且脏”或者是否有任何数据库系统实际上支持“快速、实时和脏”模式更改)
有人刚才建议的在线模式修改为MySQL从Facebook脚本(有教程这里和源在这里)......似乎是一个很好的方式来自动执行了一套“哈克”的方式来做到这一点...有没有人用它在类似于生产的东西?
Cra*_*ger 23
当您ALTER TABLE在 PostgreSQL 中发出 an时,它将使用一个ACCESS EXCLUSIVE锁来阻止所有内容,包括SELECT. 然而,这种锁可以非常简短,如果表不需要重新编写,没有新的UNIQUE,CHECK或FOREIGN KEY限制需要昂贵的全表扫描,验证等。
如果有疑问,您通常可以尝试一下!PostgreSQL 中的所有 DDL 都是事务性的,因此ALTER TABLE如果它花费太长时间并开始阻止其他查询,则取消它是很好的。锁定页面中记录了各种命令所需的锁定级别。
一些通常较慢的操作可以加速,以确保安全执行而无需停机。例如,如果您有一个表t并且您想将列更改customercode integer NOT NULL为text因为客户已决定所有客户代码现在必须以 开头X,您可以编写:
ALTER TABLE t ALTER COLUMN customercode TYPE text USING ( 'X'||customercode::text );
Run Code Online (Sandbox Code Playgroud)
...但这会锁定整个表以进行重写。添加带有DEFAULT. 可以通过几个步骤来避免长锁,但应用程序必须能够处理临时重复:
ALTER TABLE t ADD COLUMN customercode_new text;
BEGIN;
LOCK TABLE t IN EXCLUSIVE MODE;
UPDATE t SET customercode_new = 'X'||customercode::text;
ALTER TABLE t DROP COLUMN customercode;
ALTER TABLE t RENAME COLUMN customercode_new TO customercode;
COMMIT;
Run Code Online (Sandbox Code Playgroud)
这只会防止写入到t在该过程; 锁名称EXCLUSIVE有点欺骗性,因为它排除了除SELECT;之外的所有内容;该ACCESS EXCLUSIVE模式是唯一排除绝对一切的模式。请参阅锁定模式。由于 所需的锁升级,此操作可能会出现死锁回滚的风险ALTER TABLE,但最坏的情况是您只需要再次执行此操作。
你甚至可以避开锁,并通过创建触发器功能做全活的东西t,只要一个INSERT或UPDATE到来时,会自动填充customercode_new从customercode。
还有一些内置工具,如CREATE INDEX CONCURRENTLY和ALTER TABLE ... ADD table_constraint_using_index旨在允许 DBA 通过以并发友好的方式更慢地完成工作来减少独占锁定持续时间。
该pg_reorg工具或其后继工具pg_repack也可用于某些表重组操作。
Percona 提出了自己的工具来执行在线模式更改
它涉及触发器,因此请仔细阅读文档。
根据文档,完成的主要操作是
关闭系统并立即进行所有更改可能非常危险。如果出现问题,并且经常出现问题,则没有简单的方法可以恢复。
作为敏捷开发人员,我有时需要在没有任何停机时间的情况下重构表,因为这些表正在被修改和读取。
以下方法风险较低,因为更改是在几个非常容易回滚的低风险步骤中完成的:
我们已经多次使用这种方法来更改大型实时生产表,而无需停机,完全没有问题。
| 归档时间: |
|
| 查看次数: |
50775 次 |
| 最近记录: |