pg_cron : https://access.crunchydata.com/documentation/pg_cron/1.3.1/
위의 문서를 보면 pg 9.5 이상부터 사용할 수 있다고 나오는데, 최신버전으로 컴파일 해 보면 V10부터 사용이 가능하다.
테스트 환경은 V9.3 ~ V14까지 source를 이용하여 하나의 서버에 설치 된 상태이다.
pg_cron을 rpm을 이용하여 설치 할 경우 source코드를 컴파일 해서 설치 하였으므로, PostgreSQL Server가 설치 되어 있지 않다고 하면서 설치가 진행이 되질 않는다.
그래서 source 컴파일을 하는 방식으로 진행을 함
postgres 유저에게 sudo 권한을 부여한 후에 postgres유저로 Engine Home을 변경해 가면서 설치 진행
여러 버전을 컴파일 해야 하므로, pg_cron 원본을 하나 따로 만들어 놓고, Engine(버전) 변경 시 마다 pg_cron 디렉터리를 새로 생성하면서 컴파일 진행
1. Download
su - postgres cd /engine git clone https://github.com/citusdata/pg_cron.git -- 다운 받은 원본은 pg_cron_org으로 변경 mv pg_cron pg_cron_org |
2. pg_cron 설치
V95 | su - postgres cd /engine rm -rf pg_cron cp -R pg_cron_org pg_cron cd pg_cron -- 환경변수 확인 env $PATH /engine/pg9.5/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/engine/embluk/bin -- 컴파일 make && sudo PATH=$PATH make install gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -std=c99 -Wall -Wextra -Werror -Wno-unused-parameter -Wno-implicit-fallthrough -Iinclude -I/engine/pg9.5/include -I. -I./ -I/engine/pg9.5/include/postgresql/server -I/engine/pg9.5/include/postgresql/internal -D_GNU_SOURCE -c -o src/pg_cron.o src/pg_cron.c src/pg_cron.c: In function ‘ManageCronTask’: src/pg_cron.c:1689:5: error: passing argument 1 of ‘shm_mq_detach’ from incompatible pointer type [-Werror] shm_mq_detach(responseq); ^ In file included from src/pg_cron.c:26:0: /engine/pg9.5/include/postgresql/server/storage/shm_mq.h:66:13: note: expected ‘struct shm_mq *’ but argument is of type ‘struct shm_mq_handle *’ extern void shm_mq_detach(shm_mq *); ^ src/pg_cron.c: At top level: cc1: error: unrecognized command line option "-Wno-implicit-fallthrough" [-Werror] cc1: all warnings being treated as errors make: *** [src/pg_cron.o] Error 1 |
V96 | su - postgres cd /engine rm -rf pg_cron cp -R pg_cron_org pg_cron cd pg_cron -- 환경변수 확인 env $PATH /engine/pg9.6/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/engine/embluk/bin -- 컴파일 make && sudo PATH=$PATH make install gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -std=c99 -Wall -Wextra -Werror -Wno-unused-parameter -Wno-implicit-fallthrough -Iinclude -I/engine/pg9.6/include -I. -I./ -I/engine/pg9.6/include/postgresql/server -I/engine/pg9.6/include/postgresql/internal -D_GNU_SOURCE -c -o src/pg_cron.o src/pg_cron.c src/pg_cron.c: In function ‘ManageCronTask’: src/pg_cron.c:1689:5: error: passing argument 1 of ‘shm_mq_detach’ from incompatible pointer type [-Werror] shm_mq_detach(responseq); ^ In file included from src/pg_cron.c:26:0: /engine/pg9.6/include/postgresql/server/storage/shm_mq.h:66:13: note: expected ‘struct shm_mq *’ but argument is of type ‘struct shm_mq_handle *’ extern void shm_mq_detach(shm_mq *); ^ src/pg_cron.c: At top level: cc1: error: unrecognized command line option "-Wno-implicit-fallthrough" [-Werror] cc1: all warnings being treated as errors make: *** [src/pg_cron.o] Error 1 |
V10 | su - postgres cd /engine rm -rf pg_cron cp -R pg_cron_org pg_cron cd pg_cron -- 환경변수 확인 env $PATH /engine/pg10.20/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/engine/embluk/bin -- 컴파일 make && sudo PATH=$PATH make install gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -std=c99 -Wall -Wextra -Werror -Wno-unused-parameter -Wno-implicit-fallthrough -Iinclude -I/engine/pg10.20/include -I. -I./ -I/engine/pg10.20/include/postgresql/server -I/engine/pg10.20/include/postgresql/internal -D_GNU_SOURCE -c -o src/pg_cron.o src/pg_cron.c gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -std=c99 -Wall -Wextra -Werror -Wno-unused-parameter -Wno-implicit-fallthrough -Iinclude -I/engine/pg10.20/include -I. -I./ -I/engine/pg10.20/include/postgresql/server -I/engine/pg10.20/include/postgresql/internal -D_GNU_SOURCE -c -o src/job_metadata.o src/job_metadata.c gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -std=c99 -Wall -Wextra -Werror -Wno-unused-parameter -Wno-implicit-fallthrough -Iinclude -I/engine/pg10.20/include -I. -I./ -I/engine/pg10.20/include/postgresql/server -I/engine/pg10.20/include/postgresql/internal -D_GNU_SOURCE -c -o src/misc.o src/misc.c gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -std=c99 -Wall -Wextra -Werror -Wno-unused-parameter -Wno-implicit-fallthrough -Iinclude -I/engine/pg10.20/include -I. -I./ -I/engine/pg10.20/include/postgresql/server -I/engine/pg10.20/include/postgresql/internal -D_GNU_SOURCE -c -o src/task_states.o src/task_states.c gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -std=c99 -Wall -Wextra -Werror -Wno-unused-parameter -Wno-implicit-fallthrough -Iinclude -I/engine/pg10.20/include -I. -I./ -I/engine/pg10.20/include/postgresql/server -I/engine/pg10.20/include/postgresql/internal -D_GNU_SOURCE -c -o src/entry.o src/entry.c gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -shared -o pg_cron.so src/pg_cron.o src/job_metadata.o src/misc.o src/task_states.o src/entry.o -L/engine/pg10.20/lib -Wl,--as-needed -Wl,-rpath,'/engine/pg10.20/lib',--enable-new-dtags -L/engine/pg10.20/lib -lpq cat pg_cron.sql > pg_cron--1.0.sql /bin/mkdir -p '/engine/pg10.20/lib/postgresql' /bin/mkdir -p '/engine/pg10.20/share/postgresql/extension' /bin/mkdir -p '/engine/pg10.20/share/postgresql/extension' /bin/install -c -m 755 pg_cron.so '/engine/pg10.20/lib/postgresql/pg_cron.so' /bin/install -c -m 644 .//pg_cron.control '/engine/pg10.20/share/postgresql/extension/' /bin/install -c -m 644 .//pg_cron--1.3--1.4.sql .//pg_cron--1.2--1.3.sql .//pg_cron--1.0--1.1.sql .//pg_cron--1.4--1.4-1.sql .//pg_cron--1.1--1.2.sql pg_cron--1.0.sql '/engine/pg10.20/share/postgresql/extension/' # add to postgresql.conf: shared_preload_libraries = 'pg_cron' cron.database_name = 'postgres' -- run as superuser: CREATE EXTENSION pg_cron; |
V11 | su - postgres cd /engine rm -rf pg_cron cp -R pg_cron_org pg_cron cd pg_cron -- 환경변수 확인 env $PATH /engine/pg11.15/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/engine/embluk/bin -- 컴파일 make && sudo PATH=$PATH make install gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -std=c99 -Wall -Wextra -Werror -Wno-unused-parameter -Wno-implicit-fallthrough -Iinclude -I/engine/pg11.15/include -I. -I./ -I/engine/pg11.15/include/postgresql/server -I/engine/pg11.15/include/postgresql/internal -D_GNU_SOURCE -c -o src/pg_cron.o src/pg_cron.c gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -std=c99 -Wall -Wextra -Werror -Wno-unused-parameter -Wno-implicit-fallthrough -Iinclude -I/engine/pg11.15/include -I. -I./ -I/engine/pg11.15/include/postgresql/server -I/engine/pg11.15/include/postgresql/internal -D_GNU_SOURCE -c -o src/job_metadata.o src/job_metadata.c gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -std=c99 -Wall -Wextra -Werror -Wno-unused-parameter -Wno-implicit-fallthrough -Iinclude -I/engine/pg11.15/include -I. -I./ -I/engine/pg11.15/include/postgresql/server -I/engine/pg11.15/include/postgresql/internal -D_GNU_SOURCE -c -o src/misc.o src/misc.c gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -std=c99 -Wall -Wextra -Werror -Wno-unused-parameter -Wno-implicit-fallthrough -Iinclude -I/engine/pg11.15/include -I. -I./ -I/engine/pg11.15/include/postgresql/server -I/engine/pg11.15/include/postgresql/internal -D_GNU_SOURCE -c -o src/task_states.o src/task_states.c gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -std=c99 -Wall -Wextra -Werror -Wno-unused-parameter -Wno-implicit-fallthrough -Iinclude -I/engine/pg11.15/include -I. -I./ -I/engine/pg11.15/include/postgresql/server -I/engine/pg11.15/include/postgresql/internal -D_GNU_SOURCE -c -o src/entry.o src/entry.c gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -shared -o pg_cron.so src/pg_cron.o src/job_metadata.o src/misc.o src/task_states.o src/entry.o -L/engine/pg11.15/lib -Wl,--as-needed -Wl,-rpath,'/engine/pg11.15/lib',--enable-new-dtags -L/engine/pg11.15/lib -lpq cat pg_cron.sql > pg_cron--1.0.sql /bin/mkdir -p '/engine/pg11.15/lib/postgresql' /bin/mkdir -p '/engine/pg11.15/share/postgresql/extension' /bin/mkdir -p '/engine/pg11.15/share/postgresql/extension' /bin/install -c -m 755 pg_cron.so '/engine/pg11.15/lib/postgresql/pg_cron.so' /bin/install -c -m 644 .//pg_cron.control '/engine/pg11.15/share/postgresql/extension/' /bin/install -c -m 644 .//pg_cron--1.3--1.4.sql .//pg_cron--1.2--1.3.sql .//pg_cron--1.0--1.1.sql .//pg_cron--1.4--1.4-1.sql .//pg_cron--1.1--1.2.sql pg_cron--1.0.sql '/engine/pg11.15/share/postgresql/extension/' # add to postgresql.conf: shared_preload_libraries = 'pg_cron' cron.database_name = 'postgres' -- run as superuser: CREATE EXTENSION pg_cron; |
3. pg_cron 사용하기
postgresql.conf 파일에 설정을 하고 기동을 하게 되면, pg_cron launcher라는 프로세스가 기동되는 것을 확인 할 수 있다.
[postgres@postgres pg11.15]$ ps -u postgres uf USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND postgres 17189 0.0 0.0 115680 2224 pts/1 S May12 0:00 -bash postgres 22367 0.0 0.0 155448 1844 pts/1 R+ 11:19 0:00 \_ ps -u postgres uf postgres 16937 0.0 0.0 115680 2236 pts/0 S+ May12 0:00 -bash postgres 22124 0.0 0.6 406832 50876 pts/1 S 09:53 0:00 /engine/pg11.15/bin/postgres -D /data/pg11.15 postgres 22125 0.0 0.0 133668 940 ? Ss 09:53 0:00 \_ postgres: logger postgres 22127 0.0 0.0 406984 3236 ? Ss 09:53 0:00 \_ postgres: checkpointer postgres 22128 0.0 0.0 406964 2200 ? Ss 09:53 0:00 \_ postgres: background writer postgres 22129 0.0 0.0 406964 5096 ? Ss 09:53 0:00 \_ postgres: walwriter postgres 22130 0.0 0.0 407384 2124 ? Ss 09:53 0:00 \_ postgres: autovacuum launcher postgres 22131 0.0 0.0 136064 1236 ? Ss 09:53 0:00 \_ postgres: stats collector postgres 22132 0.0 0.0 408672 7700 ? Ss 09:53 0:00 \_ postgres: pg_cron launcher postgres 22133 0.0 0.0 407280 1664 ? Ss 09:53 0:00 \_ postgres: logical replication launcher |
사용 설정은 O/S의 cron과 설정 방법이 같다
┌───────────── min (0 - 59) │ ┌────────────── hour (0 - 23) │ │ ┌─────────────── day of month (1 - 31) │ │ │ ┌──────────────── month (1 - 12) │ │ │ │ ┌───────────────── day of week (0 - 6) (0 to 6 are Sunday to │ │ │ │ │ Saturday, or use names; 7 is also Sunday) │ │ │ │ │ │ │ │ │ │ * * * * * |
create extension을 수행하게 되면, cron 스키마가 생성이 되고, 등록 된 Job과 Job 수행결과를 확인 할 수 있는 테이블 과 Job 등록 및 삭제를 할 수 있는 프로시저를 가지게 된다.
select current_database() , current_user ; +------------------+--------------+ | current_database | current_user | +------------------+--------------+ | postgres | postgres | +------------------+--------------+ -- 파라미터 SHOW cron.log_run; +--------------+ | cron.log_run | +--------------+ | on | +--------------+ SELECT name, setting, short_desc FROM pg_settings WHERE name LIKE 'cron.%' ORDER BY name; +-----------------------------+-----------+----------------------------------------------------+ | name | setting | short_desc | +-----------------------------+-----------+----------------------------------------------------+ | cron.database_name | postgres | Database in which pg_cron metadata is kept. | | cron.enable_superuser_jobs | on | Allow jobs to be scheduled as superuser | | cron.host | localhost | Hostname to connect to postgres. | | cron.log_min_messages | warning | log_min_messages for the launcher bgworker. | | cron.log_run | on | Log all jobs runs into the job_run_details table | | cron.log_statement | on | Log all cron statements prior to execution. | | cron.max_running_jobs | 32 | Maximum number of jobs that can run concurrently. | | cron.use_background_workers | off | Use background workers instead of client sessions. | +-----------------------------+-----------+----------------------------------------------------+ -- 스키마 \dn List of schemas +--------+----------+ | Name | Owner | +--------+----------+ | cron | postgres | | public | postgres | +--------+----------+ select * from pg_namespace ; +--------------------+----------+-------------------------------------+ | nspname | nspowner | nspacl | +--------------------+----------+-------------------------------------+ | pg_toast | 10 | NULL | | pg_temp_1 | 10 | NULL | | pg_toast_temp_1 | 10 | NULL | | pg_catalog | 10 | {postgres=UC/postgres,=U/postgres} | | public | 10 | {postgres=UC/postgres,=UC/postgres} | | information_schema | 10 | {postgres=UC/postgres,=U/postgres} | | cron | 10 | NULL | +--------------------+----------+-------------------------------------+ -- 테이블 select relname , n.nspname as schema , pg_catalog.pg_get_userbyid(c.relowner) as "Owner" from pg_class c , pg_namespace n where c.relnamespace = n.oid and n.nspname = 'cron' and c.relkind = 'r' ; +-----------------+--------+----------+ | relname | schema | Owner | +-----------------+--------+----------+ | job_run_details | cron | postgres | | job | cron | postgres | +-----------------+--------+----------+ SELECT * FROM cron.job; +-------+----------+---------+----------+----------+----------+----------+--------+---------+ | jobid | schedule | command | nodename | nodeport | database | username | active | jobname | +-------+----------+---------+----------+----------+----------+----------+--------+---------+ +-------+----------+---------+----------+----------+----------+----------+--------+---------+ select * from cron.job_run_details ; +-------+-------+---------+----------+----------+---------+--------+----------------+------------+----------+ | jobid | runid | job_pid | database | username | command | status | return_message | start_time | end_time | +-------+-------+---------+----------+----------+---------+--------+----------------+------------+----------+ +-------+-------+---------+----------+----------+---------+--------+----------------+------------+----------+ -- 프로시저 select n.nspname as schema , (select rolname from pg_authid a where a.oid = p.proowner) as owner , p.proname as procedure_name , p.proargnames as args from pg_proc p , pg_namespace n where p.pronamespace = n.oid and n.nspname not like 'pg_%' and n.nspname not in ('information_schema' , 'public') ; +--------+----------+----------------------+------------------------------------------------------+ | schema | owner | procedure_name | args | +--------+----------+----------------------+------------------------------------------------------+ | cron | postgres | schedule | {schedule,command} | | cron | postgres | unschedule | {job_id} | | cron | postgres | job_cache_invalidate | NULL | | cron | postgres | unschedule | {job_name} | | cron | postgres | schedule | {job_name,schedule,command} | | cron | postgres | alter_job | {job_id,schedule,command,database,username,active} | | cron | postgres | schedule_in_database | {job_name,schedule,command,database,username,active} | +--------+----------+----------------------+------------------------------------------------------+ |
나중에 Job을 삭제 하기 편하기 위해서 job name을 이용하여 잡을 생성하고 삭제를 진행 하도록 하자
기본으로 cron 스키마가 postgres에 설치 되었기 때문에 postgres DB에서 기본적으로 실행이 된다.
다른 DB에서 수행해야 할 명령을 Job으로 생성하려면, schedule_in_database 프로시저를 이용해서 database 이름과 username을 입력해 주면 동작 된다.
3.1 postgres DB에서 사용하기
-- 테스트 테이블 생성
create table test_cron ( id serial , insertdate timestamp ) ;
-- 현재 시간 확인
select now() ;
+-------------------------------+
| now |
+-------------------------------+
| 2022-05-13 10:46:21.162693+09 |
+-------------------------------+
-- Job 생성
select cron.schedule('test_cron_insert' , '50 * * * *' , $$insert into test_cron(insertdate) values (now()) $$) ;
+----------+
| schedule |
+----------+
| 5 |
+----------+
-- Job 동작 확인
SELECT * FROM cron.job_run_details WHERE jobid = 5 ;
+-------+-------+---------+----------+----------+---------------------------------------------------+-----------+----------------+-------------------------------+-------------------------------+
| jobid | runid | job_pid | database | username | command | status | return_message | start_time | end_time |
+-------+-------+---------+----------+----------+---------------------------------------------------+-----------+----------------+-------------------------------+-------------------------------+
| 5 | 4 | 22283 | postgres | postgres | insert into test_cron(insertdate) values (now()) | succeeded | INSERT 0 1 | 2022-05-13 10:50:00.260626+09 | 2022-05-13 10:50:00.264431+09 |
+-------+-------+---------+----------+----------+---------------------------------------------------+-----------+----------------+-------------------------------+-------------------------------+
select * from test_cron ;
+----+---------------------------+
| id | insertdate |
+----+---------------------------+
| 1 | 2022-05-13 10:50:00.26082 |
+----+---------------------------+
3.2 다른 데이터베이스에서 사용하기
-- 데이터 베이스 변경
\c test
select current_database() , current_user ;
+------------------+--------------+
| current_database | current_user |
+------------------+--------------+
| test | postgres |
+------------------+--------------+
-- 테스트 테이블 생성
create table test_cron_test ( id serial , insertdate timestamp ) ;
-- Job 생성 (postgres DB에서 생성)
/c postgres
select current_database() , current_user ;
+------------------+--------------+
| current_database | current_user |
+------------------+--------------+
| postgres | postgres |
+------------------+--------------+
select cron.schedule_in_database('test_cron_insert1' , '57 * * * *' , $$insert into test_cron_test(insertdate) values (now()) $$ , 'test', 'postgres') ;
+----------------------+
| schedule_in_database |
+----------------------+
| 6 |
+----------------------+
SELECT * FROM cron.job_run_details WHERE jobid = 6 ;
+-------+-------+---------+----------+----------+--------------------------------------------------------+-----------+----------------+-------------------------------+-------------------------------+
| jobid | runid | job_pid | database | username | command | status | return_message | start_time | end_time |
+-------+-------+---------+----------+----------+--------------------------------------------------------+-----------+----------------+-------------------------------+-------------------------------+
| 6 | 5 | 22302 | test | postgres | insert into test_cron_test(insertdate) values (now()) | succeeded | INSERT 0 1 | 2022-05-13 10:57:00.049459+09 | 2022-05-13 10:57:00.052424+09 |
+-------+-------+---------+----------+----------+--------------------------------------------------------+-----------+----------------+-------------------------------+-------------------------------+
-- Job 동작 확인
\c test
select * from test_cron_test ;
+----+----------------------------+
| id | insertdate |
+----+----------------------------+
| 1 | 2022-05-13 10:57:00.049657 |
+----+----------------------------+
3.3 Job 삭제
\c postgres
select cron.unschedule('test_cron_insert') ;
+------------+
| unschedule |
+------------+
| t |
+------------+
select cron.unschedule('test_cron_insert1') ;
+------------+
| unschedule |
+------------+
| t |
+------------+
DELETE FROM cron.job_run_details ;