На этом шаге мы рассмотрим понятие транзакции и особенности ее использования.
Очень часто несколько инструкций выполняются последовательно. Например, при совершении покупки деньги списываются со счета клиента и сразу добавляются на счет магазина. Если во время добавления денег на счет магазина произойдет ошибка, то деньги будут списаны со счета клиента, но не попадут на счет магазина. Чтобы гарантировать успешное выполнение группы инструкций, предназначены транзакции. После запуска транзакции группа инструкций выполняется как единое целое. Если во время транзакции произойдет ошибка - например, отключится компьютер, все операции с начала транзакции будут отменены.
В SQLite каждая инструкция, производящая изменения в базе данных, автоматически запускает транзакцию, если таковая не была запущена ранее. После завершения выполнения инструкции транзакция автоматически завершается.
Для явного запуска транзакции предназначена инструкция BEGIN. Формат инструкции:
BEGIN [DEFERRED | IMMEDIATE | EXCLUSIVE] [TRANSACTION];
Чтобы нормально завершить транзакцию, следует выполнить инструкции COMMIT или END - любая из них сохраняет все изменения и завершает транзакцию. Инструкции имеют следующий формат:
COMMIT [TRANSACTION]; END [TRANSACTION];
Чтобы отменить изменения, выполненные с начала транзакции, используется инструкция ROLLBACK. Формат инструкции:
ROLLBACK [TRANSACTION] [TO [SAVEPOINT] <Название метки>];
Для примера запустим транзакцию, вставим две записи, а затем отменим все произведенные изменения и выведем содержимое таблицы:
Рис.1. Пример использования транзакции
Как видно из результата, новые записи не были вставлены в таблицу. Аналогичные действия будут выполнены автоматически, если соединение с базой данных закроется или отключится компьютер.
Когда ошибка возникает в одной из инструкций внутри транзакции, то запускается алгоритм обработки ошибок, указанный в конструкции ON CONFLICT <Алгоритм> при создании таблицы или в конструкции OR <Алгоритм> при вставке или обновлении записей. По умолчанию используется алгоритм ABORT. Согласно этому алгоритму при возникновении ошибки аннулируются все изменения, произведенные текущей командой, и выводится соответствующее сообщение. Все изменения, сделанные предыдущими командами в транзакции, сохраняются. Запустим транзакцию и попробуем вставить две записи. При вставке второй записи укажем индекс, который уже существует в таблице:
Рис.2. Пример транзакции с ошибочными данными
Как видно из примера, первая запись успешно добавлена в таблицу.
Если необходимо отменить все изменения внутри транзакции, то при вставке следует указать алгоритм ROLLBACK. Согласно этому алгоритму при ошибке транзакция завершается с откатом всех измененных ранее записей, дальнейшее выполнение прерывается, и выводится сообщение об ошибке. Рассмотрим это на примере:
Рис.3. Пример транзакции с алгоритмом ROLLBACK
В процессе выполнения транзакции база данных блокируется, после чего ни одна другая транзакция не сможет внести в нее изменения, пока не будет выполнена операция завершения (COMMIT или END) или отмены (ROLLBACK). Это делается во избежание конфликтов, когда разные транзакции пытаются внести изменения в одну и ту же запись таблицы.
Мы имеем возможность управлять режимом блокировки базы данных. Для этого при ее запуске после ключевого слова BEGIN следует указать обозначение нужного режима:
В большинстве случаев используется режим блокировки DEFERRED. Остальные режимы применяются лишь в особых случаях.
Пример запуска транзакции, полностью блокирующей базу:
Рис.4. Пример транзакции с полной блокировкой базы
Вместо запуска транзакции с помощью инструкции BEGIN можно создать именованную метку, выполнив инструкцию SAVEPOINT. Формат инструкции:
SAVEPOINT <Название метки>;
Для нормального завершения транзакции и сохранения всех изменений предназначена инструкция RELEASE. Формат инструкции:
RELEASE [SAVEPOINT] <Название метки>;
Чтобы отменить изменения, выполненные после метки, используется инструкция ROLLBACK. В качестве примера запустим транзакцию, вставим две записи, а затем отменим все произведенные изменения и выведем содержимое таблицы:
Рис.5. Пример отмены изменений после метки
На следующем шаге мы рассмотрим удаление таблицы и базы данных.