×
Мы обрабатываем cookies, чтобы сделать наш сайт удобнее и персонализированнее для вас. Подробнее: политика использования «cookies» и «политики конфиденциальности».

Для самостоятельной настройки ознакомьтесь с инструкцией

Дополнительные настройки cookies в браузерах

Файлы cookie автоматически загружаются в ваш браузер при посещении веб-сайта. У вас есть возможность управлять этими файлами. Если Вы не согласны с использованием файлов cookies, запретите их сохранение на своём устройстве, удалите уже имеющиеся файлы cookies через настройки браузера или прекратите использование сайта.

При отключении обработки cookie наш сайт продолжит функционировать, однако будут использоваться исключительно необходимые технические файлы, без которых работа ресурса невозможна.

Инструкция по отключению cookies
Принять
Настроить
Отклонить

ДОКУМЕНТАЦИЯ

Выберите версию, форк и язык для СУБД Digital Q.DataBase, чтобы прочитать или скачать всю документацию.
Техподдержка
Документация
Диасофт
Авторские права © 2016–2025 ООО "Диасофт Экосистема"
Скачать всю документацию:

5.7.9. Явные подтранзакции в PL/Tcl

Восстановление после ошибок, возникших при доступе к базе данных, как описано в Раздел 5.7.8 может привести к нежелательной ситуации, когда часть операций выполняется успешно до возникновения ошибки в одной из них, и после восстановления данные остаются в несогласованном состоянии. PL/Tcl предлагает решение этой проблемы в виде использования явных подтранзакций.

Рассмотрим функцию, реализующую перевод денежных средств между двумя счетами:

CREATE FUNCTION transfer_funds() RETURNS void AS $$
    if [catch {
        spi_exec "UPDATE accounts SET balance = balance - 100 WHERE account_name = 'joe'"
        spi_exec "UPDATE accounts SET balance = balance + 100 WHERE account_name = 'mary'"
    } errormsg] {
        set result [format "ошибка при переводе средств: %s" $errormsg]
    } else {
        set result "перевод средств выполнен успешно"
    }
    spi_exec "INSERT INTO operations (result) VALUES ('[quote $result]')"
$$ LANGUAGE pltcl;

Если вторая UPDATE инструкция приведет к возникновению исключения, эта функция зафиксирует ошибку в журнале, но результат выполнения первой UPDATE будет тем не менее зафиксирован. Другими словами, денежные средства будут списаны со счета Джо, но не будут переведены на счет Мэри. Это происходит потому, что каждая spi_exec инструкция выполняется как отдельная подтранзакция, и только одна из этих подтранзакций была откачена.

Для обработки таких случаев можно обернуть несколько операций базы данных в явную подтранзакцию, которая будет зафиксирована или откачена как единое целое. PL/Tcl предоставляет подтранзакция команду для управления этим процессом. Мы можем переписать нашу функцию следующим образом:

CREATE FUNCTION transfer_funds2() RETURNS void AS $$
    if [catch {
        subtransaction {
            spi_exec "UPDATE accounts SET balance = balance - 100 WHERE account_name = 'joe'"
            spi_exec "UPDATE accounts SET balance = balance + 100 WHERE account_name = 'mary'"
        }
    } errormsg] {
        set result [format "ошибка при переводе средств: %s" $errormsg]
    } else {
        set result "перевод средств выполнен успешно"
    }
    spi_exec "INSERT INTO operations (result) VALUES ('[quote $result]')"
$$ LANGUAGE pltcl;

Обратите внимание, что использование catch по-прежнему требуется для этой цели. В противном случае ошибка распространится на верхний уровень функции, что предотвратит выполнение вставки в таблицу operations . Данная команда подтранзакция не перехватывает ошибки; она лишь гарантирует, что все операции с базой данных, выполненные в её области действия, будут откачены совместно при возникновении ошибки.

Откат явной подтранзакции происходит при любой ошибке, инициируемой кодом Tcl, а не только при ошибках, возникающих при доступе к базе данных. Таким образом, стандартное исключение Tcl, возникшее внутри команды подтранзакция также приведет к откату подтранзакции. Однако штатные завершения вложенного кода Tcl (например, вследствие return) не приводят к откату.

Наверх
свяжитесь
с нами
контакты
Для прямой связи с нами вы можете использовать контакты ниже, либо оставить заявку через форму обратной связи, и мы обязательно свяжемся с вами

*поля обязательные к заполнению