Транзакция/transaktsioonid – это последовательность операций, выполняемых в логическом порядке пользователем, либо программой, которая работает с БД.
Транзакция – это распространение изменений в БД. Например, если мы создаём, изменяем или удаляем запись, то мы выполняем транзакцию. Крайне важно контролировать транзакции для гарантирования.
Основные концепции транзакции описываются аббревиатурой ACID –
- Atomicity – Атомарность
- Consistency – Согласованность
- Isolation – Изолированность
- Durability – Долговечность
Для управления транзакциями используются следующие команды:
- COMMIT
Сохраняет изменения - ROLLBACK
Откатывает (отменяет) изменения - SAVEPOINT
Создаёт точку к которой группа транзакций может откатиться - SET TRANSACTION
Размещает имя транзакции.
Команды управление транзакциями используются только для DML команд: INSERT, UPDATE, DELETE. Они не могут быть использованы во время создания, изменения или удаления таблицы.
Любое успешное выполнение транзакции заканчивается командой COMMIT (фиксация), в то время как неудачное выполнение должно быть закончено командой ROLLBACK (откат), которая автоматически восстанавливает в базе данных все изменения, внесенные транзакцией.
Таким образом, SQL транзакция может также рассматриваться в качестве элемента восстановления.
Преимущество команды ROLLBACK (в стандартном SQL) состоит в том, что когда запрограммированная в транзакции логика приложения не может быть завершена, то нет никакой необходимости в проведении серии обратных операций отдельными командами, работа может быть просто отменена командой ROLLBACK, действие которой будет всегда успешно выполняться. Незавершенные транзакции в случае разрыва соединения, завершения программы или отказа системы будут автоматически выполнять откат системы.
Некоторые СУБД (SQL-сервер, MySQL/InnoDB, PostgreSQL) работают в режиме AUTOCOMMIT по умолчанию.
Это означает, что результат каждой отдельной команды SQL будет автоматически фиксироваться в базе данных, таким образом эффекты и/или изменения, выполненные в базе данных рассматриваемым оператором, не могут быть отменены до прежнего состояния.
Так, в случае ошибок приложение должно выполнить обратные операции для логической единицы работы, которые могут быть невозможными после операций параллельных (конкурирующих) SQL-клиентов.
create database transactionTARgv24;
use transactionTARgv24;
create table T(
id int not null primary key,
s varchar(40),
si smallint)
insert into T(id, s) values(1, 'fisrt');
insert into T(id, s) values(2, 'second');
insert into T(id, s) values(3, 'third');
select * from T;
--tagasi votmine
rollback;
--alustame transaction
begin transaction; --xampp start transaction
insert into T(id, s) values(4, 'fourth');
select * from T;
--tagasi votmine
rollback;
select * from T;
begin transaction;
delete from T where id > 1;
select * from T;
rollback;
select * from T;
--transaktsioon salvestab uuendamine ja votab tagasi
begin transaction;
update T set si = 3;
select * from T;
rollback;
select * from T;
Ülesanne
SQL
Создаём в базе данных transactionTARgv24 две таблицы Employee(Работники), EmployeeAddress(Адреса работников) и вставляем необходимые данные в таблицы.

Создаём процедуру, которая будет подставлять значения LONDON в таблицу Employee в поле City, где номер работника – 7 и адрес улицы Mäealuse, и в таблицу EmployeeAddress в поле City, где номер ид адреса равен 1 и номер работника равен 7. Если транзакция прошла успешно, то данные меняются в обеих таблицах.

Транзакция прошла успешно и данные поменяны.

Теперь меняем процедуру, подставляя другие значения в те же самые поля, как и в предыдущей процедуре, но умышленно ставим большее значение в поле City для таблицы EmployeeAddress.
Для поля City в обеих таблицах стоит ограничение: City nvarchar(10), что означает не больше 10 символов.
Цель транзакции – это откат к прошлой версии таблицы.
Что это означает:
Когда вызывается spUpdateAddress:
- Сначала меняем город в таблице Employee на ‘Tallinn’ – это работает
- Потом пытаемся изменить город в EmployeeAddress на ‘Tallinn Tallinn Tallinn’ – но здесь ошибка
- Как только возникает ошибка:
- Все изменения отменяются (как будто ничего не было)
- Город в обеих таблицах остаётся прежним
Итог: если хоть что-то пойдёт не так – ничего не изменится. Либо обновятся обе таблицы, либо ни одна.


Как мы видими на скриншоте ниже, транзакция прошла успешно и произошёл откат к прошлой версии таблиц.

Снова меняем процедуру, подставим значения в поля City – Tallinn.


Транзакция прошла успешно.

XAMPP
Та же работа в xampp.
Создаём две таблицы, вносим в них данные.




Проверяем, что данные введены корректно.

Создаём процедуру для изменения данных в полях City для обеих таблиц, как было сделано в SQL.

DELIMITER //
Временно изменяет разделитель команд с;
на//
, чтобы MySQL правильно интерпретировал тело процедуры.CREATE PROCEDURE spUpdateAddress()
Объявляет создание новой хранимой процедуры с именемspUpdateAddress
.BEGIN ... END
Ограничивает тело процедуры.DECLARE EXIT HANDLER
– объявляет обработчик, который завершает процедуру при ошибкеFOR SQLEXCEPTION
– реагирует на любые SQL-ошибкиROLLBACK
– откатывает текущую транзакцию
- Последовательность выполнения:
- Старт процедуры
- Регистрация обработчика ошибок
- Начало транзакции
- Первое обновление (Employee)
- Второе обновление (EmployeeAddress)
- Фиксация изменений (если успешно)
- Или откат (при ошибке)
Вызываем функцию ->

Проверяем таблицы.

Транзакция прошла успешно, данные поменяны.

Чтобы сделать Alter procedure, как было сделано в SQL, в XAMPP в таком случае мы сначала сбрасываем функцию и только потом создаём на её место новую.


Процедура пытается изменить данные в двух таблицах:
- Сначала в таблице Employee
- Потом в таблице EmployeeAddress
- Если вторая операция (с EmployeeAddress) даст ошибку:
- Автоматически отменятся ОБЕ операции (и первая тоже) и данные будут возвращены в их исходный вид, то есть будет совершён ROLLBACK – откат всей транзакции.
- Если ошибки не будет – сохранятся изменения в обеих таблицах
Как показано на скриншоте ниже, транзакция сделала ROLLBACK, откатила данные.

Снова сбрасываем действующую процедуру.

И создаём новую, подставляя новые данные в поля City в обеих таблицах.


Транзакция прошла успешно.
