pg_cron 是 PostgreSQL(9.5或更高版本)的一个简单的基于cron的作业调度程序,它作为扩展在数据库中运行。它与常规 cron 保持相同的语法,但它允许直接从数据库安排 PostgreSQL 命令。作为一个独立运行的工作者进程,其生命周期管理、内存空间都依赖于 postgreSQL 。本文主要从启动、生命周期、状态机、用法介绍该插件在 postgresQL 数据库中的应用。
postgresql 后台的主进程是 postmaster, 在其启动时,会调用一个函数process_shared_preload_libraries(); 这个函数被 postgresql 用来预加载外部插件。该函数会遍历参数列表,然后对列表参数中的插件依次进行加载。对于插件来说加载的过程包括了除了检查环境 和 注册主函数,主函数由插件中的 _PG_init() 完成注册,这个函数从外部环境中 加载进来,被postmaster执行(类似 Python 的反射)。
PG_init = (PG_init_t) pg_dlsym(file_scanner->handle, "_PG_init");
if (PG_init)
(*PG_init) ();
对于 pg_cron 插件来说,插件的 _PG_init 函数对于主函数进行了注册:将 PgCronWorkerMain配置为一个后台 worker 并且注册到列表中。到这里系统回到了 postmaster 进程中继续执行任务,直到执行到 maybe_start_bgworkers() 函数,尝试将 workerlist 列表中的worker启动。(这个执行的过程还与数据库的模式有关,处于 standby mode 状态下的数据库不会去启动 pg_cron) postmaster 会分配一个 background work给pg_cron , 之后pg_cron 进程独立运行。
pg_cron 生命周期
pg_cron 插件的主体是围绕 PG_CRON_TASK 进行,从内部来说, PG_CRON_TASK 有自己的生命周期,其生命周期的轮转过程就是插件的运行过程,从外部来说 PG_CRON_TASK 与 PG_CRON_JOB 通信取得当前的任务列表,在运行状态与 POSTMASTER 通信 完成定时任务的运行。
pg_cron 通信状态机
pg_cron 用法手册
增加任务项
-- 周六3:30am (GMT) 删除过期数据
SELECT cron.schedule('30 3 * * 6', $$DELETE FROM events WHERE event_time < now() - interval '1 week'$$);
schedule
----------
42
-- 每天的 10:00am (GMT) 执行磁盘清理
SELECT cron.schedule('0 10 * * *', 'VACUUM');
schedule
----------
43
-- 每分钟执行 指定脚本
SELECT cron.schedule('* * * * *', 'select 1;');
schedule
----------
44
-- 每个小时的 23分 执行 指定脚本
SELECT cron.schedule('23 * * * *', 'select 1;');
schedule
----------
45
-- 每个月的 4号 执行 指定脚本
SELECT cron.schedule('* * 4 * *', 'select 1;');
schedule
----------
46
pg_cron
计划使用标准的 cron
语法,其中 * 表示“每个该时间运行”,特定数字表示“仅在 这个数字时 运行”┌───────────── 分钟 (0 - 59)
│ ┌────────────── 小时 (0 - 23)
│ │ ┌─────────────── 日期 (1 - 31)
│ │ │ ┌──────────────── 月份 (1 - 12)
│ │ │ │ ┌───────────────── 一周中的某一天 (0 - 6) (0 到 6 表示周末到下周六,
│ │ │ │ │ 7 仍然是周末)
│ │ │ │ │
│ │ │ │ │
* * * * *
-- 停止、删除一个任务
SELECT cron.unschedule(42);
unschedule
------------
t
SELECT * FROM cron.job;
jobid | schedule | command | nodename | nodeport | database | username | active
-------+------------+-----------+-----------+----------+----------+----------+--------
43 | 0 10 * * * | VACUUM; | localhost | 5433 | postgres | test | t