合 PG实现定时任务的几种方法
Tags: PG定时任务jobpg_cronpg_timetablepgAgent
简介
数据库定时任务可以用于实现定期的备份、统计信息采集、数据汇总、数据清理与优化等。PostgreSQL 没有提供类似 Oracle、MySQL 以及 Microsoft SQL Sever 的内置任务调度功能,本文介绍在 PostgreSQL 数据库中实现定时任务的 4 种方法,包括操作系统定时任务、pgAgent 代理、pg_cron 插件以及 pg_timetable 工具。
方法1:操作系统定时任务
Linux 定时任务(crontab)或者 Windows 任务计划程序(Task Scheduler)为我们提供了一个实现定时任务传统的方法。以 crontab 为例,我们可以使用以下命令编辑任务列表:
1 | crontab -e |
然后在打开的文件中使用以下格式增加一行数据:
1 2 3 | #分钟 小时 月份中的某一天 月份 星期 命令 #(0-59) (0-23) (1-31) (1-12) (0-7 [7 or 0 == Sunday]) <minute> <hour> <day of month> <month> <day of week> <command> |
其中的前五个字段表示执行命令的时间,可以使用星号(*)匹配所有的时间。例如,将
举例来说,输入以下内容表示每天零点执行数据库逻辑备份操作。
1 | 0 0 * * * pg_dump --no-password -U user db_name > backup.sql |
为了安全起见不要直接输入密码,而是应该将密码加入 .pgpass 文件,并且将该文件的权限设置为仅当前用户可见:
1 | chmod 600 .pgpass |
方法2:pgAgent
pgAgent 是一个用于 PostgreSQL 数据库的任务调度代理,能够基于复杂的调度计划运行多步骤的批处理、shell 脚本以及 SQL 命令。
对于 Unix/Linux 系统,pgAgent 以后台进程的方式运行;对于 Windows 系统,pgAgent 以服务的形式运行。
pgAgent is a job scheduler for PostgreSQL which may be managed using pgAdmin. Prior to pgAdmin v1.9, pgAgent shipped as part of pgAdmin. From pgAdmin v1.9 onwards, pgAgent is shipped as a separate application.
在pgAdmin v1.9版本之前,pgAgent是其安装包的一部分,pgAdmin v1.9之后 pgAgent独立成一个单独的软件包。
PgAdmin 4 管理工具集成了 pgAgent 的功能,但是这两者需要单独安装。我们可以通过官方网站下载 PgAdmin 4 以及 pgAgent。
具体安装pgAdmin4步骤和注意事项可以参考:https://www.dbaup.com/dbbao71postgresqltuxinghuajiemiangongjuzhipgadmin4.html
安装 pgAgent
参考:https://www.pgadmin.org/docs/pgadmin4/latest/pgagent_install.html
需要在PG数据库服务器端安装pgAgent:
可以直接yum安装,也可以编译安装(参考:https://blog.csdn.net/ctypyb2002/article/details/77855209)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | [root@lhrpg yum.repos.d]# yum list | grep pgagent pgagent_13.x86_64 4.2.1-0.rhel7 @pgdg13 pgagent_10.x86_64 4.2.1-0.rhel7 pgdg10 pgagent_11.x86_64 4.2.1-0.rhel7 pgdg11 pgagent_12.x86_64 4.2.1-0.rhel7 pgdg12 pgagent_96.x86_64 4.2.1-0.rhel7 pgdg96 [root@lhrpg soft]# yum install -y pgagent_13.x86_64 -- 大概3M大小 Dependencies Resolved ========================================================= Package ========================================================= Installing: pgagent_13 Installing for dependencies: boost-atomic boost-chrono boost-date-time boost-filesystem boost-regex Transaction Summary ========================================================= Install 1 Package (+5 Dependent packages) Total download size: 623 k Installed size: 2.9 M Downloading packages: (1/6): boost-atomic-1.53.0-28.el7.x86_64.rpm (2/6): boost-date-time-1.53.0-28.el7.x86_64.rpm (3/6): boost-filesystem-1.53.0-28.el7.x86_64.rpm (4/6): boost-regex-1.53.0-28.el7.x86_64.rpm (5/6): boost-chrono-1.53.0-28.el7.x86_64.rpm (6/6): pgagent_13-4.2.1-0.rhel7.x86_64.rpm --------------------------------------------------------- 。。。。。。。。。。 [root@lhrpg soft]# rpm -ql pgagent_13-4.2.1-0.rhel7.x86_64 /etc/logrotate.d/pgagent_13 /etc/pgagent /etc/pgagent/pgagent_13.conf /run/pgagent /usr/bin/pgagent_13 /usr/lib/systemd/system/pgagent_13.service /usr/lib/tmpfiles.d/pgagent_13.conf /usr/pgsql-13/share/extension/pgagent--3.4--4.2.sql /usr/pgsql-13/share/extension/pgagent--4.0--4.2.sql /usr/pgsql-13/share/extension/pgagent--4.1--4.2.sql /usr/pgsql-13/share/extension/pgagent--4.2.sql /usr/pgsql-13/share/extension/pgagent--unpackaged--4.2.sql /usr/pgsql-13/share/extension/pgagent.control /usr/share/doc/pgagent_13-4.2.1 /usr/share/doc/pgagent_13-4.2.1/README /usr/share/licenses/pgagent_13-4.2.1 /usr/share/licenses/pgagent_13-4.2.1/LICENSE /usr/share/pgagent_13-4.2.1/pgagent.sql -- 参数文件 [root@lhrpg ~]# cat /etc/pgagent/pgagent_13.conf DBNAME=postgres DBUSER=postgres DBHOST=127.0.0.1 DBPORT=5432 LOGFILE=/var/log/pgagent_13.log -- 创建 [postgres@lhrpg ~]$ psql psql (13.3) Type "help" for help. postgres=# create extension pgagent; CREATE EXTENSION postgres=# CREATE LANGUAGE plpgsql; ERROR: extension "plpgsql" already exists postgres=# exit -- 启动pgagent [root@lhrpg ~]# systemctl start pgagent_13.service [root@lhrpg ~]# systemctl status pgagent_13.service ● pgagent_13.service - PgAgent for PostgreSQL 13 Loaded: loaded (/usr/lib/systemd/system/pgagent_13.service; disabled; vendor preset: disabled) Active: active (running) since Fri 2021-08-13 12:47:36 CST; 2h 29min ago Process: 25125 ExecStart=/usr/bin/pgagent_13 -s ${LOGFILE} hostaddr=${DBHOST} dbname=${DBNAME} user=${DBUSER} port=${DBPORT} (code=exited, status=0/SUCCESS) Main PID: 25126 (pgagent_13) CGroup: /docker/8f6ede0f912cbec4e9cb3725e9871873ad1fdf51ae61779482f9126ec2b29e3e/system.slice/pgagent_13.service └─25126 /usr/bin/pgagent_13 -s /var/log/pgagent_13.log hostaddr=127.0.0.1 dbname=postgres user=postgres port=5432 Aug 13 12:47:36 lhrpg systemd[1]: Starting PgAgent for PostgreSQL 13... Aug 13 12:47:36 lhrpg systemd[1]: Started PgAgent for PostgreSQL 13. |
安装完成之后,我们可以在 PgAdmin 4 左侧导航树中看到“pgAgent Jobs”节点。
创建定时任务
右键点击“pgAgent Jobs”节点,选择“Create” > “pgAgent Job”创建一个新的定时任务。
其中,“General”页面可以输入一些基本信息,包括任务的名称。“Steps”页面可以设置多个操作步骤,包括执行的脚本或者 SQL 语句等。“Schedules”页面用于定义任务执行的时间计划。“SQL”页面可以显示创建或者修改任务的语句。
点击“Save”按钮保存设置并创建任务,然后我们就可以在“pgAgent Job”节点下看到创建的任务。
- 定义作业步骤
在General页定义通用信息
在code页定义需要执行的代码
- 定义调度信息
在general页定义基本信息
在Repeat页定义周期,周期使用cron风格。
以上所有操作也可以通过SQL进行,上面所有操作对应的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | DO $$ DECLARE jid integer; scid integer; BEGIN -- Creating a new job INSERT INTO pgagent.pga_job( jobjclid, jobname, jobdesc, jobhostagent, jobenabled ) VALUES ( 1::integer, 'job_test2'::text, ''::text, ''::text, true ) RETURNING jobid INTO jid; -- Steps -- Inserting a step (jobid: NULL) INSERT INTO pgagent.pga_jobstep ( jstjobid, jstname, jstenabled, jstkind, jstconnstr, jstdbname, jstonerror, jstcode, jstdesc ) VALUES ( jid, 'step1'::text, true, 's'::character(1), ''::text, 'postgres'::name, 'f'::character(1), 'insert into t1 values (999);'::text, ''::text ) ; -- Schedules -- Inserting a schedule INSERT INTO pgagent.pga_schedule( jscjobid, jscname, jscdesc, jscenabled, jscstart, jscend, jscminutes, jschours, jscweekdays, jscmonthdays, jscmonths ) VALUES ( jid, 'job_sch_test2'::text, ''::text, true, '2018-05-24 15:12:33+08'::timestamp with time zone, '2018-05-25 15:12:39+08'::timestamp with time zone, -- Minutes ARRAY[false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, true, true]::boolean[], -- Hours ARRAY[false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false]::boolean[], -- Week days ARRAY[false, false, false, false, false, false, false]::boolean[], -- Month days ARRAY[false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]::boolean[], -- Months ARRAY[false, false, false, false, false, false, false, false, false, false, false, false]::boolean[] ) RETURNING jscid INTO scid; END $$; |
再回到图形界面,除了预先定义好的作业外,通过作业上的run now选项可以立刻执行一次。
上面的设置里我选择在每天的15点56-59分,一共执行4次作业,每次向t1表写入一条数据。完成后
pgAgent的数据字典表
pgAgent的相关表都位于Catalogs/pgAgent下。
- pga_exception : 记录作业执行异常信息
- pga_job: 作业定义的基本信息,作业起止时间,最后运行时间等
- pga_jobagent:pgAgent的配置信息,服务器上pgAgent的地址和启动时间
- pga_jobclass: pgAgent的配置信息,定义作业类型
- pga_joblog:每个作业的运行日志,包含启动时间、执行时长。
- pga_jobstep每个job步骤的定义在这个表里。
- pga_jobsteplog:每个job步骤的执行日志,包含步骤的开始时间,执行时长。
- pga_schedule:job调度的定义在这个表里。
方法3:pg_cron
pgagent功能确实不错,但是需要的依赖太多了,需要先装PGadmin以及一大堆的依赖包,这导致使用起来非常不方面,很不友好。而pg_cron相对而言简单了很多,只需要编译和修改三两个参数就可以了。
pg_cron 是由 citusdata 公司开发的一个 PostgreSQL 定时任务插件(类似于 Oracle 中的 DBMS_SCHEDULER)。pg_cron 作为一个后台工作进程运行,使用类似 cron 的编辑语法,允许直接在数据库中执行定时任务。例如: