使用 PostgreSQL pg_cron 擴充功能排程維護 - Amazon Aurora

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

使用 PostgreSQL pg_cron 擴充功能排程維護

您可以使用 PostgreSQL pg_cron 擴充功能,來排程 PostgreSQL 資料庫內的維護命令。如需擴充功能的詳細資訊,請參閱 pg_cron 文件中的什麼是 pg_cron?

Aurora PostgreSQL 引擎 12.6 版以及更新版本支援 pg_cron 擴充功能。

若要深入了解如何使用 pg_cron,請參閱在 RDS for PostgreSQL 或 Aurora PostgreSQL 相容版本資料庫上使用 pg_cron 排程任務

設定 pg_cron 擴充功能

設定 pg_cron 擴充功能,如下所示:

  1. 修改與 PostgreSQL 資料庫執行個體關聯的自訂參數群組,並將 pg_cron 新增至 shared_preload_libraries 參數值。

    重新啟動 PostgreSQL 資料庫執行個體,使參數群組的變更生效。若要深入了解如何使用參數群組,請參閱 Amazon Aurora PostgreSQL 參數

  2. 重新啟動 PostgreSQL 資料庫執行個體之後,請使用具有 rds_superuser 許可的帳戶執行下列命令。例如,如果您在為 Aurora PostgreSQL 資料庫叢集 建立 RDS 時使用了預設設定,請以使用者 postgres 身分連接並建立擴充功能。

    CREATE EXTENSION pg_cron;

    pg_cron 排程器設定於名為 postgres 的預設 PostgreSQL 資料庫內。pg_cron 物件會在此 postgres 資料庫中建立,而且所有排程動作都會在此資料庫中執行。

  3. 您可以使用預設設定,或將任務排程在 PostgreSQL 資料庫執行個體的其他資料庫中執行。若要將任務排程至 PostgreSQL 資料庫執行個體中的其他資料庫,請參閱 為預設資料庫以外的資料庫排程 cron 任務 中的範例。

授與資料車使用者使用 pg_cron 的許可

安裝 pg_cron 擴充功能需要 rds_superuser 權限。然而,使用 pg_cron 的許可能夠授予 (由 rds_superuser 群組/角色的成員) 其他資料庫使用者,讓他們可以安排自己的任務。建議您只有在能改善生產環境中的作業時,才視需要授予對 cron 結構描述的許可。

若要授予資料庫使用者對 cron 結構描述的許可,請執行以下命令:

postgres=> GRANT USAGE ON SCHEMA cron TO db-user;

這樣會給予 db-user 存取 cron 結構描述的許可,以針對它們有權存取的物件排程 cron 作業。如果資料庫使用者沒有許可,則作業會在將錯誤訊息發佈至 postgresql.log 檔案後失敗,如下所示:

2020-12-08 16:41:00 UTC::@:[30647]:ERROR: permission denied for table table-name 2020-12-08 16:41:00 UTC::@:[27071]:LOG: background worker "pg_cron" (PID 30647) exited with exit code 1

換句話說,請確定被授與cron結構描述權限的資料庫使用者也擁有他們計劃排程之物件 (表格、結構描述等) 的權限。

Cron 工作的詳細資訊及其成功或失敗也會擷取在資料cron.job_run_details表中。如需詳細資訊,請參閱 用於排程工作和擷取狀態的資料表

排定 pg_cron 任務

以下各節示範如何使用 pg_cron 任務排程各種管理任務。

注意

建立 pg_cron 工作時,請檢查 max_worker_processes 設定大於數目 cron.max_running_jobs。如果 pg_cron 任務耗盡背景工作者程序,則會失敗。pg_cron 任務的預設數字為 5。如需詳細資訊,請參閱 用於管理 pg_cron 擴充功能的參數

正在清理資料表

自動資料清理功能可處理大多數情況下的清理維護。但是,您可能想要在您選定的時間來排定清理特定的資料表。

以下為使用 cron.schedule 函數來設定一個任務,以在每天 22:00 (GMT) 於特定資料表上使用 VACUUM FREEZE 的範例。

SELECT cron.schedule('manual vacuum', '0 22 * * *', 'VACUUM FREEZE pgbench_accounts'); schedule ---------- 1 (1 row)

執行上述範例之後,您可以如下所示檢查 cron.job_run_details 資料表中的歷史記錄。

postgres=> SELECT * FROM cron.job_run_details; jobid | runid | job_pid | database | username | command | status | return_message | start_time | end_time -------+-------+---------+----------+----------+--------------------------------+-----------+----------------+-------------------------------+------------------------------- 1 | 1 | 3395 | postgres | adminuser| vacuum freeze pgbench_accounts | succeeded | VACUUM | 2020-12-04 21:10:00.050386+00 | 2020-12-04 21:10:00.072028+00 (1 row)

以下是cron.job_run_details表的查詢,看到失敗的作業。

postgres=> SELECT * FROM cron.job_run_details WHERE status = 'failed'; jobid | runid | job_pid | database | username | command | status | return_message | start_time | end_time ------+-------+---------+----------+----------+-------------------------------+--------+--------------------------------------------------+-------------------------------+------------------------------ 5 | 4 | 30339 | postgres | adminuser| vacuum freeze pgbench_account | failed | ERROR: relation "pgbench_account" does not exist | 2020-12-04 21:48:00.015145+00 | 2020-12-04 21:48:00.029567+00 (1 row)

如需詳細資訊,請參閱 用於排程工作和擷取狀態的資料表

正在清除 pg_cron 歷史記錄資料表

cron.job_run_details 資料表包含 cron 任務的歷史記錄,它可能會隨著時間的推移而變得非常大。建議您排程清除此資料表的任務。例如,保留一週的項目可能足以進行疑難排解。

下列範例會使用 cron.schedule 函數來排程每天在午夜執行的任務,以清除 cron.job_run_details 資料表。這項任務只保留過去七天。如下所示使用您的 rds_superuser 帳戶來排程任務。

SELECT cron.schedule('0 0 * * *', $$DELETE FROM cron.job_run_details WHERE end_time < now() - interval '7 days'$$);

如需詳細資訊,請參閱 用於排程工作和擷取狀態的資料表

僅將錯誤記錄到 postgresql.log 檔案

若要防止寫入至 cron.job_run_details 資料表,請修改與 PostgreSQL 資料庫執行個體關聯的參數群組,並將 cron.log_run 參數設定為關閉。pg_cron 延伸模組不再寫入至資料表,而且只會將錯誤擷取至 postgresql.log 檔案。如需詳細資訊,請參閱 修改 Aurora 數據庫參數組中的參數

使用下列命令來檢查 cron.log_run 參數的值。

postgres=> SHOW cron.log_run;

如需詳細資訊,請參閱 用於管理 pg_cron 擴充功能的參數

為預設資料庫以外的資料庫排程 cron 任務

pg_cron 的中繼資料都保留在名為 postgres 的 PostgreSQL 預設資料庫中。由於使用背景工作者來執行維護 cron 任務,因此您可以在 PostgreSQL 資料庫執行個體內的任何資料庫中排程任務︰

  1. 在 cron 資料庫中,使用 cron.schedule 如常排程任務。

    postgres=> SELECT cron.schedule('database1 manual vacuum', '29 03 * * *', 'vacuum freeze test_table');
  2. 作為使用 rds_superuser 角色的使用者,請為您剛建立的任務更新資料庫欄,以便在 PostgreSQL 資料庫執行個體內的另一個資料庫中執行。

    postgres=> UPDATE cron.job SET database = 'database1' WHERE jobid = 106;
  3. 透過查詢 cron.job 資料表進行驗證。

    postgres=> SELECT * FROM cron.job; jobid | schedule | command | nodename | nodeport | database | username | active | jobname ------+-------------+--------------------------------+-----------+----------+----------+-----------+--------+------------------------- 106 | 29 03 * * * | vacuum freeze test_table | localhost | 8192 | database1| adminuser | t | database1 manual vacuum 1 | 59 23 * * * | vacuum freeze pgbench_accounts | localhost | 8192 | postgres | adminuser | t | manual vacuum (2 rows)
注意

在某些情況下,您可能會新增一個打算在其他資料庫上執行的 cron 任務。在此情況下,任務可能會嘗試在預設資料庫 (postgres) 中執行,然後再更新正確的資料庫資料欄。如果使用者名稱具有許可,則任務會在預設資料庫中成功執行。

pg_cron 擴充功能的參考

您可以使用下列參數、函數和資料表搭配 pg_cron 擴充功能。如需詳細資訊,請參閱 pg_cron 文件中的什麼是 pg_cron?

用於管理 pg_cron 擴充功能的參數

以下是用來控制 pg_cron 擴充功能行為的參數清單。

參數 描述

cron.database_name

在其中保留 pg_cron 中繼資料的資料庫。

cron.host

要連線至 PostgreSQL 的主機名稱。您無法修改此值。

cron.log_run

記錄 job_run_details 資料表執行的每個任務。值為 onoff。如需詳細資訊,請參閱 用於排程工作和擷取狀態的資料表

cron.log_statement

在執行之前記錄所有 cron 陳述式。值為 onoff

cron.max_running_jobs

可同時執行的任務數量上限。

cron.use_background_workers

使用背景工作者而不是用戶端工作階段。您無法修改此值。

使用下列 SQL 命令來顯示這些參數及其值。

postgres=> SELECT name, setting, short_desc FROM pg_settings WHERE name LIKE 'cron.%' ORDER BY name;

函數參考:cron.schedule

這個函數會排程一個 cron 任務。任務最初是在預設 postgres 資料庫中進行排程。該函數會返回表示任務識別符的 bigint 值。若要將任務排程在 PostgreSQL 資料庫執行個體中的其他資料庫中執行,請參閱 為預設資料庫以外的資料庫排程 cron 任務 中的範例。

該函數有兩種語法格式。

語法
cron.schedule (job_name, schedule, command ); cron.schedule (schedule, command );
參數
參數 描述
job_name

cron 任務的名稱。

schedule

指出 cron 任務排程的文字。格式為標準 cron 格式。

command 要執行的命令文字。
範例
postgres=> SELECT cron.schedule ('test','0 10 * * *', 'VACUUM pgbench_history'); schedule ---------- 145 (1 row) postgres=> SELECT cron.schedule ('0 15 * * *', 'VACUUM pgbench_accounts'); schedule ---------- 146 (1 row)

函數參考:cron.unschedule

這個函數會刪除 cron 任務。您可以指定 job_namejob_id,兩者之一。政策可確保您是移除任務排程的擁有者。該函數會返回一個表示成功或失敗的布林值。

此函數的語法格示如下。

語法
cron.unschedule (job_id); cron.unschedule (job_name);
參數
參數 描述
job_id

排程 cron 任務時,從 cron.schedule 函數傳回的任務識別符。

job_name

使用 cron.schedule 函數排程的 cron 任務的名稱。

範例
postgres=> SELECT cron.unschedule(108); unschedule ------------ t (1 row) postgres=> SELECT cron.unschedule('test'); unschedule ------------ t (1 row)

用於排程工作和擷取狀態的資料表

下表用於排程 cron 任務以及記錄任務完成的方式。

表格 描述
cron.job

包含每個排程任務的中繼資料。大部分與此資料表的互動應透過使用 cron.schedulecron.unschedule 函數來完成。

重要

我們建議您不要將更新或插入權限直接提供給此資料表。這樣做將允許使用者更新 username 資料欄,以 rds-superuser 身分執行任務。

cron.job_run_details

包含過去排程任務執行的歷史記錄資訊。這對於調查任務執行的狀態、傳回訊息以及開始和結束時間非常有用。

注意

若要防止此資料表無限期增長,請定期清除。如需範例,請參閱 正在清除 pg_cron 歷史記錄資料表