pg-online-schema-change (pg-osc) 是一个工具,用于以最小的锁在 PostgreSQL 表中进行模式更改(任何ALTER语句),以帮助实现在生产环境工作负载下进行零停机的模式更改。
pg-osc使用了影子表的概念来执行模式更改。在较高级别上,它会创建一个在结构上与主表相同的影子表,对影子表执行模式更改,将内容从主表复制到影子表,并在最后交换表名称,同时使用触发器(通过审计表)保留对主表的所有更改。
pg-osc受到了pt-online-schema-change (MySQL) 和pg_repack等工具的设计和工作原理的启发。可在下面阅读更多内容,关于它是如何工作的、亮点特性、注意事项和示例。
pg-online-schema-change help performUsage: pg-online-schema-change perform -a,--alter-statement=ALTER_STATEMENT -d,--dbname=DBNAME -h,--host=HOST -p,--port=N -s,--schema=SCHEMA -u,--username=USERNAMEOptions:-a,--alter-statement=ALTER_STATEMENT # The ALTER statement to perform the schema change-s,--schema=SCHEMA # The schema in which the table is. Default: public-d,--dbname=DBNAME # Name of the database-h,--host=HOST # Server host where the Database is located-u,--username=USERNAME # Username for the Database-p,--port=N # Port for the Database. Default: 5432-w,[--password=PASSWORD] # DEPRECATED: Password for the Database. Please pass PGPASSWORD environment variable instead.-v,[--verbose],[--no-verbose] # Emit logs in debug mode-f,[--drop],[--no-drop] # Drop the original table in the end after the swap-k,[--kill-backends],[--no-kill-backends] # Kill other competing queries/backends when trying to acquire lock for the shadow table creation and swap. It will wait for --wait-time-for-lock duration before killing backends and try upto 3 times.-w,[--wait-time-for-lock=N] # Time to wait before killing backends to acquire lock and/or retrying upto 3 times. Default: 10. It will kill backends if --kill-backends is true, otherwise try upto 3 times and exit if it cannot acquire a lock.-c,[--copy-statement=COPY_STATEMENT] # Takes a .sql file location where you can provide a custom query to be played (ex: backfills) when pgosc copies data from the primary to the shadow table. More examples in README.-b,[--pull-batch-count=N] # Number of rows to be replayed on each iteration after copy. Default: 1000. This can be tuned for faster catch up and swap. Best used with delta-count.-e,[--delta-count=N] # Indicates how many rows should be remaining before a swap should be performed. Default: 20. This can be tuned for faster catch up and swap, especially on highly volume tables. Best used with pull-batch-count.-o,[--skip-foreign-key-validation],[--no-skip-foreign-key-validation] # Skip foreign key validation after swap. You shouldn't need this unless you have a very specific use case, like manually validating foreign key constraints after swap.
Usage: pg-online-schema-change --version, -vprint the version
export PGPASSWORD=""pg-online-schema-change perform / --alter-statement 'ALTER TABLE books RENAME COLUMN email TO new_email' / --dbname "postgres" / --host "localhost" / --username "jamesbond"
export PGPASSWORD=""pg-online-schema-change perform / --alter-statement 'ALTER TABLE books ADD COLUMN "purchased" BOOLEAN DEFAULT FALSE; ALTER TABLE books RENAME COLUMN email TO new_email;' / --dbname "postgres" / --host "localhost" / --username "jamesbond" / --drop
如果操作是在一个繁忙的表上执行的,则可以使用pg-osc的kill-backend功能,来终止可能与pg-osc操作竞争的其他后端,以便在短时间内获取锁。pg-osc获得的ACCESS EXCLUSIVE锁只持有一小段时间,然后就释放了。您可以调整在杀死其他后端之前pg-osc应该等待多长时间(或者pg-osc是否应该在一开始就杀死后端)。
export PGPASSWORD=""pg-online-schema-change perform /--alter-statement 'ALTER TABLE books ADD COLUMN "purchased" BOOLEAN DEFAULT FALSE;' /--dbname "postgres" /--host "localhost" /--username "jamesbond" /--wait-time-for-lock5 /--kill-backends /--drop
如果表的写入吞吐量较高,则默认的重放速度可能不够用。也就是说,您可能会看到pg-osc从审计表中一次性重放 1000 行(pull-batch-count)。pg-osc还会等到审计表中的剩余行数(delta-count)为 20 后再进行交换。您可以将这些值调整为更高的值,以便更快地赶上此类工作负载。
export PGPASSWORD=""pg-online-schema-change perform /--alter-statement 'ALTER TABLE books ADD COLUMN "purchased" BOOLEAN DEFAULT FALSE;' /--dbname "postgres" /--host "localhost" /--username "jamesbond" /--pull-batch-count 2000--delta-count 500--wait-time-for-lock5 /--kill-backends /--drop
在将数据插入到影子表时,您可以传入自定义 sql 文件,来执行复制和任何其他工作,而不仅仅是从主表复制所有列和行。例如:回填某些列。通过提供copy-statement,pg-osc将改为运行查询以执行复制操作。
重要提示:
• 可能会意外违反约束或不复制数据,因此请谨慎操作。
• 在自定义 SQL 中连接时,必须使用 OUTER JOIN,否则会丢失与连接表不匹配的行。
• ALTER语句可能会更改表的结构,因此请谨慎操作。
• 保留%{shadow_table},因为它会替换为影子表的目标。
• 强烈建议用户在生产环境上使用之前,先测试和验证结果!
-- file: /src/query.sqlINSERT INTO %{shadow_table}(foo, bar, baz, rental_id, tenant_id)SELECT a.foo,a.bar,a.baz,a.rental_id,r.tenant_id AS tenant_idFROM ONLY examples aLEFT OUTER JOIN rentals rON a.rental_id = r.id
pg-online-schema-change perform / --alter-statement 'ALTER TABLE books ADD COLUMN "tenant_id" VARCHAR;' / --dbname "postgres" / --host "localhost" / --username "jamesbond" / --copy-statement "/src/query.sql" / --drop
docker run --network host -it --rm shayonj/pg-osc:latest / pg-online-schema-change perform / --alter-statement 'ALTER TABLE books ADD COLUMN "purchased" BOOLEAN DEFAULT FALSE; ALTER TABLE books RENAME COLUMN email TO new_email;' / --dbname "postgres" / --host "localhost" / --username "jamesbond" / --drop
• 目前尚不支持分区表。欢迎提供 PR 请求和想法。
• 表上应存在主键;没有的话,pg-osc会引发异常
• 这是因为,目前没有其他方法可以在重放期间唯一标识行。
• pg-osc会在操作期间两次获取父表上的ACCESS EXCLUSIVE锁。
• 第一次,在设置触发器和影子表时。
• 下一次,在执行交换和更新外键引用时。
• 注意:如果指定了kill-backends,它会尝试终止在这两个时间内的任何竞争操作。
• 根据设计,pg-osc不会终止正在执行的任何其他 DDL。在操作过程中,最好不要对父表运行任何 DDL。
• 由于复制表的性质,磁盘上需要有足够的空间来支持该操作。
• 索引、约束和序列名称会被更改,并失去其原始命名。
• 可以在将来的版本中修复。如有需要,可创建特性请求。
• 外键会被删除,并重新以NOT VALID的方式添加到引用表。接着运行VALIDATE CONSTRAINT操作。
• 要确保保持完整性,并在重新引入外键时不用获取额外的锁,因此才会使用NOT VALID。
此工具中有 3 种类型的表:
how-it-works
1. 创建一个审计表,以记录对父表所做的更改。
2. 获取一个简短的ACCESS EXCLUSIVE锁,以在父表上添加触发器,记录插入、更新、删除操作到审计表。
3. 创建一个新的影子表,并在影子表上运行 ALTER 或迁移。
4. 复制旧表中的所有行。
5. 在新表上构建索引。
6. 将审计表中累积的所有更改重放到影子表中。
• 在审计审计表中的行时,删除这些行。
7. 一旦差量行数(剩余行数)到 ~20,则在事务中获取父表上的ACCESS EXCLUSIVE锁,然后:
• 交换表名称(影子表 <> 父表)。
• 删除外键,并重新以NOT VALID的方式创建,以更新其他表中的外键引用。
8. 在新表上运行ANALYZE。
9. 验证所有添加的NOT VALID的外键。
10. 删除父表(现在是旧表)(可选)。
本文链接:http://www.28at.com/showinfo-26-100185-0.html再大的 DDL 变更操作都不怕了!一条命令直接搞定
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com
上一篇: 腾讯电商部门二面:如何保证幂等性?