Транзакции и курсоры
В PostgreSQL используется специфический подход к обработке транзакций в базах данных. В терминологии SQL транзакцией называется процесс синхронизации результатов выполнения команды с состоянием данных в базе. Данные не записываются на диск немедленно, а лишь отражаются в "текущей" информации состояния, хранящейся в базе. В результате фиксации транзакции последствия выполнения команды окончательно фиксируются в текущем состоянии базы данных.
Возникает очевидная проблема – что произойдет, если два пользователя одновременно попытаются зафиксировать взаимоисключающие изменения в одном объекте базы данных? В некоторых СУБД подобные конфликты предотвращаются путем блокировки (locking).
Блокировкой называется механизм, запрещающий выборку из объекта базы данных на время его модификации, и наоборот. Применение блокировки связано с очевидными проблемами из области быстродействия. Например, выборка заблокированных данных становится невозможной до момента завершения обновления.
В PostgreSQL используется механизм MVCC (Multi-Version Concurrency Control), позволяющий выполнять команды SQL в отложенных транзакционных блоках. Таким образом, каждое подключение к серверу PostgreSQL до фиксации результатов фактически поддерживает временный "образ" объектов базы данных, модифицируемых в транзакционном блоке.
Если в программе отсутствует команда начала транзакционного блока, все команды SQL, передаваемые PostgreSQL, фиксируются автоматически, то есть база данных синхронизируется с. результатами команд сразу же после их выполнения. Тем не менее при явном создании транзакционного блока изменения в базе данных остаются невидимыми для других пользователей вплоть до фиксации. Таким образом, появляется возможность одновременного внесения изменений в разные объекты базы данных. Далее все изменения либо фиксируются, либо откатываются (отменяются).
При откате транзакции все объекты возвращаются к состоянию, в котором они находились до начала транзакционного блока. Такая возможность может пригодиться при восстановлении после незавершенных операций или при отмене любых частичных изменений. Отмененные транзакции не фиксируются в базе данных, и другие пользователи даже не замечают последствий незавершенной транзакции.
В PostgreSQL также поддерживаются курсоры – универсальный и гибкий механизм ссылок на выполненные запросы SQL. Курсор позволяет перебрать содержимое итогового набора и включить в выборку только некоторые из полученных записей. При правильном использовании курсоры повышают эффективность работы со статическими наборами записей в приложениях. Курсоры выполняются только в транзакционных блоках.
В следующем подразделе описаны основные принципы работы с транзакциями и курсорами. В частности, в нем рассматриваются команды создания, фиксации и отката транзакций, а также способы объявления, перемещения и выборки в курсорах.
Транзакционные блоки
Транзакционные блоки создаются командой SQL BEGIN, за которой могут следовать необязательные ключевые слова WORK или TRANSACTION. Эти ключевые слова делают команду более наглядной, но никак не влияют на работу ее пли транзакционного блока.
В листинге 7.38 приведен пример создания транзакционного блока в базе данных booktown.
Листинг 7.38. Создание транзакции.
bOOktown=# BEGIN; BEGIN
С точки зрения пользователя, вносящего изменения в базу данных, все команды SQL после команды BEGIN выполняются немедленно. Но как упоминалось выше, для других пользователей эти изменения остаются невидимыми вплоть до момента фиксации транзакционного блока.