F.37. pg_cron#
F.37. pg_cron #
F.37.1. О расширении pg_cron #
Версия: 1.6.2
Страница проекта www.citusdata.com
Copyright © Citus Data, Inc.
F.37.2. Что такое pg_cron? #
pg_cron - это простой планировщик заданий на основе cron для
Tantor SE
который работает внутри базы данных в качестве расширения. Он использует ту же синтаксическую конструкцию, что и обычный cron, но позволяет вам планировать
Tantor SE
команды непосредственно из базы данных. Вы также можете использовать
[1-59] секунд
для планирования задания на основе интервала.
pg_cron также позволяет вам использовать $
для обозначения последнего дня
месяца.
-- Delete old data on Saturday at 3:30am (GMT) SELECT cron.schedule('30 3 * * 6', $$DELETE FROM events WHERE event_time < now() - interval '1 week'$$); schedule ---------- 42 -- Vacuum every day at 10:00am (GMT) SELECT cron.schedule('nightly-vacuum', '0 10 * * *', 'VACUUM'); schedule ---------- 43 -- Change to vacuum at 3:00am (GMT) SELECT cron.schedule('nightly-vacuum', '0 3 * * *', 'VACUUM'); schedule ---------- 43 -- Stop scheduling jobs SELECT cron.unschedule('nightly-vacuum' ); unschedule ------------ t SELECT cron.unschedule(42); unschedule ------------ t -- Vacuum every Sunday at 4:00am (GMT) in a database other than the one pg_cron is installed in SELECT cron.schedule_in_database('weekly-vacuum', '0 4 * * 0', 'VACUUM', 'some_other_database'); schedule ---------- 44 -- Call a stored procedure every 5 seconds SELECT cron.schedule('process-updates', '5 seconds', 'CALL process_updates()'); -- Process payroll at 12:00 of the last day of each month SELECT cron.schedule('process-payroll', '0 12 $ * *', 'CALL process_payroll()');
pg_cron может выполнять несколько заданий параллельно, но одновременно может выполняться только один экземпляр задания. Если второй запуск должен начаться до завершения первого, то второй запуск ставится в очередь и начинается сразу после завершения первого запуска.
Расписание использует стандартный синтаксис cron, в котором *
означает “запускать
каждый период времени”, а конкретное число означает “но только в это
время”:
┌───────────── min (0 - 59) │ ┌────────────── hour (0 - 23) │ │ ┌─────────────── day of month (1 - 31) or last day of the month ($) │ │ │ ┌──────────────── month (1 - 12) │ │ │ │ ┌───────────────── day of week (0 - 6) (0 to 6 are Sunday to │ │ │ │ │ Saturday, or use names; 7 is also Sunday) │ │ │ │ │ │ │ │ │ │ * * * * *
Легкий способ создать расписание cron: crontab.guru.
Код в pg_cron, который обрабатывает разбор и планирование, взят непосредственно из исходного кода cron Пола Викси, поэтому поддерживаются те же параметры.
F.37.3. Настройка pg_cron #
Чтобы запустить фоновый рабочий процесс pg_cron, когда
Tantor SE
запускается, вам
нужно добавить pg_cron в shared_preload_libraries
в postgresql.conf. Обратите внимание, что pg_cron не выполняет никаких задач, пока сервер находится в
режиме горячего резерва, но он автоматически запускается, когда статус сервера
повышается.
# add to postgresql.conf # required to load pg_cron background worker on start-up shared_preload_libraries = 'pg_cron'
По умолчанию фоновый рабочий процесс pg_cron ожидает, что его метаданные таблицы будут созданы в базе данных “postgres”.
Однако, вы можете настроить это, установив параметр конфигурации cron.database_name
в файле postgresql.conf.
# add to postgresql.conf # optionally, specify the database in which the pg_cron background worker should run (defaults to postgres) cron.database_name = 'postgres'
pg_cron
может быть установлен только в одну базу данных в кластере.
Если необходимо запускать задания в нескольких базах данных, используйте cron.schedule_in_database()
.
Ранее pg_cron мог использовать только время по Гринвичу, но теперь вы можете адаптировать
ваше время, установив cron.timezone
в
postgresql.conf.
# add to postgresql.conf # optionally, specify the timezone in which the pg_cron background worker should run (defaults to GMT). E.g: cron.timezone = 'PRC'
После перезапуска
Tantor SE
,
вы можете создать функции pg_cron и метаданные таблиц, используя
CREATE EXTENSION pg_cron
.
-- run as superuser: CREATE EXTENSION pg_cron; -- optionally, grant usage to regular users: GRANT USAGE ON SCHEMA cron TO marco;
F.37.3.1. Обеспечение возможности запуска заданий pg_cron #
Предостережение
По умолчанию,
pg_cron использует libpq для открытия нового соединения с локальной
базой данных, что должно быть разрешено
pg_hba.conf.
Возможно, потребуется включить аутентификацию trust
для соединений, поступающих с localhost для пользователя, выполняющего задание cron, или вы можете добавить пароль в
файл .pgpass, который libpq будет использовать при открытии соединения.
Вы также можете использовать каталог сокетов домена Unix в качестве имени хоста
и включить аутентификацию trust
для локальных
подключений в
pg_hba.conf,
что обычно безопасно:
# Connect via a unix domain socket: cron.host = '/tmp' # Can also be an empty string to look for the default directory: cron.host = ''
В качестве альтернативы, pg_cron может быть настроен для использования фоновых
рабочих процессов. В этом случае количество одновременных заданий ограничено
параметром max_worker_processes
, поэтому вам может
потребоваться его увеличить.
# Schedule jobs via background workers instead of localhost connections cron.use_background_workers = on # Increase the number of available background workers from the default of 8 max_worker_processes = 20
Для обеспечения безопасности задания выполняются в базе данных, в которой вызывается функция cron.schedule
с теми же разрешениями, что и у текущего пользователя. Кроме того, пользователи могут видеть только свои собственные задания в таблице cron.job
.
F.37.4. Просмотр деталей выполнения задания #
Вы можете просмотреть статус выполняющихся и недавно завершенных заданий
в cron.job_run_details
:
select * from cron.job_run_details order by start_time desc limit 5; ┌───────┬───────┬─────────┬──────────┬──────────┬───────────────────┬───────────┬──────────────────┬───────────────────────────────┬───────────────────────────────┐ │ jobid │ runid │ job_pid │ database │ username │ command │ status │ return_message │ start_time │ end_time │ ├───────┼───────┼─────────┼──────────┼──────────┼───────────────────┼───────────┼──────────────────┼───────────────────────────────┼───────────────────────────────┤ │ 10 │ 4328 │ 2610 │ postgres │ marco │ select process() │ succeeded │ SELECT 1 │ 2023-02-07 09:30:00.098164+01 │ 2023-02-07 09:30:00.130729+01 │ │ 10 │ 4327 │ 2609 │ postgres │ marco │ select process() │ succeeded │ SELECT 1 │ 2023-02-07 09:29:00.015168+01 │ 2023-02-07 09:29:00.832308+01 │ │ 10 │ 4321 │ 2603 │ postgres │ marco │ select process() │ succeeded │ SELECT 1 │ 2023-02-07 09:28:00.011965+01 │ 2023-02-07 09:28:01.420901+01 │ │ 10 │ 4320 │ 2602 │ postgres │ marco │ select process() │ failed │ server restarted │ 2023-02-07 09:27:00.011833+01 │ 2023-02-07 09:27:00.72121+01 │ │ 9 │ 4320 │ 2602 │ postgres │ marco │ select do_stuff() │ failed │ job canceled │ 2023-02-07 09:26:00.011833+01 │ 2023-02-07 09:26:00.22121+01 │ └───────┴───────┴─────────┴──────────┴──────────┴───────────────────┴───────────┴──────────────────┴───────────────────────────────┴───────────────────────────────┘ (10 rows)
Записи в cron.job_run_details
не очищаются автоматически, но каждый пользователь, который может планировать задания cron, также имеет разрешение на удаление своих собственных записей cron.job_run_details
.
Особенно когда у вас есть задания, которые выполняются каждые несколько секунд, может быть хорошей идеей регулярно очищать, что можно легко сделать с помощью самого pg_cron:
-- Delete old cron.job_run_details records of the current user every day at noon SELECT cron.schedule('delete-job-run-details', '0 12 * * *', $$DELETE FROM cron.job_run_details WHERE end_time < now() - interval '7 days'$$);
Если вы вообще не хотите использовать cron.job_run_details
,
то вы можете добавить cron.log_run = off
в
postgresql.conf
.