更改实时生产数据库上的表

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. 然而,这种锁可以非常简短,如果表不需要重新编写,没有新的UNIQUECHECKFOREIGN KEY限制需要昂贵的全表扫描,验证等。

如果有疑问,您通常可以尝试一下!PostgreSQL 中的所有 DDL 都是事务性的,因此ALTER TABLE如果它花费太长时间并开始阻止其他查询,则取消它是很好的。锁定页面记录了各种命令所需的锁定级别。

一些通常较慢的操作可以加速,以确保安全执行而无需停机。例如,如果您有一个表t并且您想将列更改customercode integer NOT NULLtext因为客户已决定所有客户代码现在必须以 开头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,只要一个INSERTUPDATE到来时,会自动填充customercode_newcustomercode

还有一些内置工具,如CREATE INDEX CONCURRENTLYALTER TABLE ... ADD table_constraint_using_index旨在允许 DBA 通过以并发友好的方式更慢地完成工作来减少独占锁定持续时间。

pg_reorg工具或其后继工具pg_repack也可用于某些表重组操作。


Rol*_*DBA 7

Percona 提出了自己的工具来执行在线模式更改

该工具名为pt-online-schema-change

它涉及触发器,因此请仔细阅读文档。

根据文档,完成的主要操作是

  • 健全性检查
  • 分块
  • 在线模式更改
    • 创建和更改临时表
    • 捕获从表到临时表的更改
    • 将表中的行复制到临时表
    • 同步表和临时表
    • 交换/重命名表和临时表
    • 清理


A-K*_*A-K 6

关闭系统并立即进行所有更改可能非常危险。如果出现问题,并且经常出现问题,则没有简单的方法可以恢复。

作为敏捷开发人员,我有时需要在没有任何停机时间的情况下重构表,因为这些表正在被修改和读取。

以下方法风险较低,因为更改是在几个非常容易回滚的低风险步骤中完成的:

  • 确保访问表的所有模块都被自动化测试很好地覆盖。
  • 创建一个新表。更改修改旧表的所有过程,以便它们同时修改旧表和新表。
  • 将现有数据迁移到新结构中。以小批量进行,以免严重影响服务器的整体性能。
  • 验证数据迁移是否成功。
  • 将一些选择过程从旧表重定向到新表。使用自动化测试来确保更改的模块仍然正确。确保它们的性能是可以接受的。部署更改后的程序。
  • 重复上一步,直到所有报告都使用新表。
  • 更改修改表的过程,以便它们只能访问新表。
  • 归档旧表并将其从系统中删除。

我们已经多次使用这种方法来更改大型实时生产表,而无需停机,完全没有问题。

  • 太好了……但这正是我想要避免的“痛苦”类型:) (4认同)