pg-online-schema-change (pg-osc) 是一個(gè)工具,用于以最小的鎖在 PostgreSQL 表中進(jìn)行模式更改(任何ALTER語(yǔ)句),以幫助實(shí)現(xiàn)在生產(chǎn)環(huán)境工作負(fù)載下進(jìn)行零停機(jī)的模式更改。
pg-osc使用了影子表的概念來執(zhí)行模式更改。在較高級(jí)別上,它會(huì)創(chuàng)建一個(gè)在結(jié)構(gòu)上與主表相同的影子表,對(duì)影子表執(zhí)行模式更改,將內(nèi)容從主表復(fù)制到影子表,并在最后交換表名稱,同時(shí)使用觸發(fā)器(通過審計(jì)表)保留對(duì)主表的所有更改。
pg-osc受到了pt-online-schema-change (MySQL) 和pg_repack等工具的設(shè)計(jì)和工作原理的啟發(fā)。可在下面閱讀更多內(nèi)容,關(guān)于它是如何工作的、亮點(diǎn)特性、注意事項(xiàng)和示例。
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
如果操作是在一個(gè)繁忙的表上執(zhí)行的,則可以使用pg-osc的kill-backend功能,來終止可能與pg-osc操作競(jìng)爭(zhēng)的其他后端,以便在短時(shí)間內(nèi)獲取鎖。pg-osc獲得的ACCESS EXCLUSIVE鎖只持有一小段時(shí)間,然后就釋放了。您可以調(diào)整在殺死其他后端之前pg-osc應(yīng)該等待多長(zhǎng)時(shí)間(或者pg-osc是否應(yīng)該在一開始就殺死后端)。
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
如果表的寫入吞吐量較高,則默認(rèn)的重放速度可能不夠用。也就是說,您可能會(huì)看到pg-osc從審計(jì)表中一次性重放 1000 行(pull-batch-count)。pg-osc還會(huì)等到審計(jì)表中的剩余行數(shù)(delta-count)為 20 后再進(jìn)行交換。您可以將這些值調(diào)整為更高的值,以便更快地趕上此類工作負(fù)載。
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
在將數(shù)據(jù)插入到影子表時(shí),您可以傳入自定義 sql 文件,來執(zhí)行復(fù)制和任何其他工作,而不僅僅是從主表復(fù)制所有列和行。例如:回填某些列。通過提供copy-statement,pg-osc將改為運(yùn)行查詢以執(zhí)行復(fù)制操作。
重要提示:
? 可能會(huì)意外違反約束或不復(fù)制數(shù)據(jù),因此請(qǐng)謹(jǐn)慎操作。
? 在自定義 SQL 中連接時(shí),必須使用 OUTER JOIN,否則會(huì)丟失與連接表不匹配的行。
? ALTER語(yǔ)句可能會(huì)更改表的結(jié)構(gòu),因此請(qǐng)謹(jǐn)慎操作。
? 保留%{shadow_table},因?yàn)樗鼤?huì)替換為影子表的目標(biāo)。
? 強(qiáng)烈建議用戶在生產(chǎn)環(huán)境上使用之前,先測(cè)試和驗(yàn)證結(jié)果!
-- 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
? 目前尚不支持分區(qū)表。歡迎提供 PR 請(qǐng)求和想法。
? 表上應(yīng)存在主鍵;沒有的話,pg-osc會(huì)引發(fā)異常
? 這是因?yàn)椋壳皼]有其他方法可以在重放期間唯一標(biāo)識(shí)行。
? pg-osc會(huì)在操作期間兩次獲取父表上的ACCESS EXCLUSIVE鎖。
? 第一次,在設(shè)置觸發(fā)器和影子表時(shí)。
? 下一次,在執(zhí)行交換和更新外鍵引用時(shí)。
? 注意:如果指定了kill-backends,它會(huì)嘗試終止在這兩個(gè)時(shí)間內(nèi)的任何競(jìng)爭(zhēng)操作。
? 根據(jù)設(shè)計(jì),pg-osc不會(huì)終止正在執(zhí)行的任何其他 DDL。在操作過程中,最好不要對(duì)父表運(yùn)行任何 DDL。
? 由于復(fù)制表的性質(zhì),磁盤上需要有足夠的空間來支持該操作。
? 索引、約束和序列名稱會(huì)被更改,并失去其原始命名。
? 可以在將來的版本中修復(fù)。如有需要,可創(chuàng)建特性請(qǐng)求。
? 外鍵會(huì)被刪除,并重新以NOT VALID的方式添加到引用表。接著運(yùn)行VALIDATE CONSTRAINT操作。
? 要確保保持完整性,并在重新引入外鍵時(shí)不用獲取額外的鎖,因此才會(huì)使用NOT VALID。
此工具中有 3 種類型的表:
how-it-works
1. 創(chuàng)建一個(gè)審計(jì)表,以記錄對(duì)父表所做的更改。
2. 獲取一個(gè)簡(jiǎn)短的ACCESS EXCLUSIVE鎖,以在父表上添加觸發(fā)器,記錄插入、更新、刪除操作到審計(jì)表。
3. 創(chuàng)建一個(gè)新的影子表,并在影子表上運(yùn)行 ALTER 或遷移。
4. 復(fù)制舊表中的所有行。
5. 在新表上構(gòu)建索引。
6. 將審計(jì)表中累積的所有更改重放到影子表中。
? 在審計(jì)審計(jì)表中的行時(shí),刪除這些行。
7. 一旦差量行數(shù)(剩余行數(shù))到 ~20,則在事務(wù)中獲取父表上的ACCESS EXCLUSIVE鎖,然后:
? 交換表名稱(影子表 <> 父表)。
? 刪除外鍵,并重新以NOT VALID的方式創(chuàng)建,以更新其他表中的外鍵引用。
8. 在新表上運(yùn)行ANALYZE。
9. 驗(yàn)證所有添加的NOT VALID的外鍵。
10. 刪除父表(現(xiàn)在是舊表)(可選)。
本文鏈接:http://www.tebozhan.com/showinfo-26-100185-0.html再大的 DDL 變更操作都不怕了!一條命令直接搞定
聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com
上一篇: 騰訊電商部門二面:如何保證冪等性?