Как автоматически остановить запрос PostgreSQL, когда таблица заблокирована? - PullRequest
2 голосов
/ 01 февраля 2020

У меня есть сценарий bash, который создает новые разделы для таблиц в базе данных. В настоящее время у меня проблема с заблокированными таблицами - когда этот скрипт запускается и пытается создать разделы для таблицы, которая используется в противном случае, он застревает. Все, что мне нужно, это найти способ остановить скрипт через определенное время, когда таблица заблокирована, но пока мне это не удалось.

Это блок кода, в котором возникает проблема:

>&3 2>&4 psql -h $host -d $database -U $database_user -t -e -c "ALTER TABLE ${schema}.${table} SPLIT DEFAULT PARTITION START (date '${partition_date_to_create}') INCLUSIVE END (date '${exclusive_date}') EXCLUSIVE INTO (PARTITION \""${partition_name}"\", PARTITION ${default_partition_name})"

Это часть этого блока:

  do
    partition_name="${partition_date_to_create//-/}"
    if [ -n "${existent_partition[*]}" ] && [[ "${existent_partition[*]}" == *"$partition_name"* ]]; then
        log_info "Table ${table} already has partition '${partition_name}'. Skipping creation."
        continue
    fi

    log_info "Creating partition '${partition_name}' for table ${table}..."
    exclusive_date=$(date --date="${partition_date_to_create} +1 day" +%F)
    >&3 2>&4 psql -h $host -d $database -U $database_user -t -e -c "ALTER TABLE ${schema}.${table} SPLIT DEFAULT PARTITION START (date '${partition_date_to_create}') INCLUSIVE END (date '${exclusive_date}') EXCLUSIVE INTO (PARTITION \""${partition_name}"\", PARTITION ${default_partition_name})"

    if [ "$?" -eq 0 ]; then
      log_info "Created partition '${partition_name}' for table ${table}."
    else
      log_error "Error creating partition '${partition_name}' for table ${table}."
    fi
  done

Что я пробовал до сих пор:

  • Установите для переменной ON_ERROR_STOP значение ON;
  • Настроить LOCK_TIMEOUT;
  • Настроить STATEMENT_TIMEOUT;
  • Отключить функцию автоматической фиксации и зафиксировать вручную.

Может кто-нибудь подсказать мне, что я делаю неправильно?

Ответы [ 2 ]

2 голосов
/ 01 февраля 2020

Попробуйте выполнить psql для 'alter table' в Linux 'timeout`. Это заставит команду прерваться и прервет команду postgres connection / pending (аналогично Ctrl / C).

timeout 60s psql -h $host -d $database -U $database_user -t -e -c "ALTER TABLE ..."
1 голос
/ 01 февраля 2020

Используемое решение timeout великолепно и просто. Однако это может быть более точным:

#!/bin/bash
psql -c "<your statement here>" & # start job in background
pid=$! # get PID of it
sleep 2 # wait for a time (2 sec here)
locktype=$(psql -AXt -c "select wait_event_type from pg_stat_activity where pid = $pid") # get the lock type for te PID
if [[ ${locktype,,} =~ '*lock*' ]] ; then # if session is still locked then kill it
    psql -c "select pg_cancel_backend($pid)"
fi

PS: вместо '*lock*' вы должны указать свой c тип ожидания.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...