Ülesanne transaktsioonid

Расмотрим пример с видео

Первым примером, приводят пример транзакцию на обновления записи в таблице

Можем расмотреть свой пример на основе нашей таблице T

В своем примере я использовала точно свою таблицу, в ней я заменяла значения в колонки si где был id = 1 (от себя я добавила SELECT после UPDATE чтобы увидить как замениться), после этого откатила назад rollback

Так же ввидео показывают, что если мы начнем транзакцию (но не сделаем ей rollback / commit ) другие пользователи не смогут быстро соедиться с таблицей.

Будем пробовать:

Запустили первые две строчки

Открываем новый запрос и пытаемся обратиться к нашей таблице через

SELECT * FROM T;

Мы получаем, что другой кто использует эту таблицу не может выполнить сейчас запрос на таблицу T

Чтобы все же прочитать дату мы должны использовать прочитать не закоментированые данные транзакции

Воспользуемся :

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
означает установку самого низкого уровня изоляции транзакций в SQL Server.


📌 Что такое уровни изоляции?

Уровень изоляции транзакции определяет, какие данные может читать транзакция, если эти данные временно изменены другими транзакциями.

🔍 Что делает READ UNCOMMITTED?

  • Позволяет читать данные, которые были изменены другими транзакциями, но ещё не зафиксированы ( COMMIT).

Теперь мы сделаем запрос на SELECT чтобы увидить не зафиксированые данные

Теперь мы откатим rollback данные в запросе (51)

Другой пользователь, после нового select запроса увидить измененые данные

Чтобы транзакция закрепилась, надо обязательно фиксировать ее (commit), чтобы другие пользователи могли работать с базой данных

Чтобы зафиксировать транзакцию можно воспользоваться commit

Дальше расмотрим пример на том, что сделаем транзакцию, которая будет сама проверять если ошибка откативатся назад, если все верно тогда фиксировать результат

Пример, который расматриваем на ролике

К этому примеру, мы тоже сделаем две таблицы, которые будут иметь наш физический адресс и почтовый адресс. Только наша таблица будет выглядить чуть проще чем на примере

Далее создаем процедуру

Разберем процедуру:

Она обновляет два разных адреса (почтовый и физический) на новый город — 'TALLINN'. И делает это в рамках транзакции, то есть либо обновляются обе записи, либо ни одна, если произошла ошибка.


CREATE PROCEDURE spUpdateAddress
AS
BEGIN


➡️ Создание хранимой процедуры без параметров.

BEGIN TRY
    BEGIN TRANSACTION;

➡️ Начинается блок TRY и транзакция — это означает, что все следующие действия будут выполняться как единое целое.

    UPDATE postiaddress 
    SET linn = 'TALLINN'
    WHERE id = 1 AND aadress = 'kivila';

➡️ Обновляет строку в таблице postiaddress (почтовый адрес), устанавливая город linn = ‘TALLINN’, если:

id = 1

aadress = ‘kivila’

    UPDATE fuusiline_address 
    SET linn = 'TALLINN'
    WHERE id = 2;

➡️ Обновляет строку в таблице fuusiline_address (физический адрес), устанавливая город ‘TALLINN’, если id = 2.

    COMMIT TRANSACTION;
    PRINT 'TRANSACTION KOMMITERITUD';

➡️ Если обе команды UPDATE прошли успешно, изменения сохраняются (коммитятся), и выводится сообщение: “Транзакция зафиксирована”.

END TRY
BEGIN CATCH
    ROLLBACK TRANSACTION;
    PRINT 'TRANSACTION TAGASI VÕTMINE';
END CATCH

➡️ Если в любой из UPDATE возникает ошибка, выполняется откат всей транзакции, и выводится сообщение: “Транзакция отменена”.

Далее смотрим две таблицы

и пробуем запустить процедуру

После запуска процедуры мы видим, что два поля было затронуто. Смотрим на результат

и мы видим, то что просили в первом изменено по id 1 а во второй по id 2 (желания автора так сделать, чтобы не повторят по видео а пробовать свое что то)

Далее будем пробовать вызвать ошибку, для начала, посмотрим, что у нас в linn максимум 15 символов

Изменим нашу процедуру, чтобы выйти за эти рамки

На этот раз мы изменили процедуру, чтобы посмотреть если будет больше чем 15 символов (изменять будем id 3). Процедура была успешна изменена.

Наша процедура, в первом случаии должна сработать, но т.к. воторая ее часть выходит за рамки 15 символов должна будет сделать ROLLBACK

И именно это мы и видим, первое поле устаривает, но при второй операции мы делам ROLLBACK – т.к. 'TALLINN TALLINN' – превышаем 15 символов.

XAMPP

Здесь в основном мы сделаем процедуру, чтобы посмотреть как она работает (до этого сделаю две таблицы) (больше скринов будет)

Пробуем простой запрос сделать

Все получилось и затем вернулось обратно

Далее подготовка к процедуре с танзакцией

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

Далее создаем процедуру

BEGIN
  DECLARE exit handler FOR SQLEXCEPTION
  BEGIN
    ROLLBACK;
    SELECT 'TRANSACTION TAGASI VÕTMINE' AS message;
  END;

  START TRANSACTION;

  UPDATE postiaadress 
  SET linn = uus_linn 
  WHERE id = post_id AND aadress = post_aadress;

  UPDATE fuusiline_aadress 
  SET linn = uus_linn 
  WHERE id = fuus_id;

  COMMIT;
  SELECT 'TRANSACTION KOMMITERITUD' AS message;
END
SQL Server (T-SQL)MySQL (XAMPP / phpMyAdmin)
BEGIN TRY / CATCHDECLARE ... HANDLER FOR SQLEXCEPTION
PRINTSELECT 'text' AS message
BEGIN TRANSACTIONSTART TRANSACTION
BEGIN

Начало тела процедуры.

DECLARE exit handler FOR SQLEXCEPTION

exit handler — означает, что если произойдёт ошибка (исключение), выполнение немедленно перейдёт в следующий блок.

FOR SQLEXCEPTION — означает: любая SQL-ошибка (например, неверный ID, проблемы с таблицей, и т.д.).

BEGIN
  ROLLBACK;
  SELECT 'TRANSACTION TAGASI VÕTMINE' AS message;
END;

Это тело обработчикаю

ROLLBACK; — отменяет всю транзакцию, если произошла ошибка.

SELECT 'TRANSACTION TAGASI VÕTMINE' AS message; — показывает сообщение: “Транзакция отменена” (по-эстонски).

⚠️ Этот блок выполнится только в случае ошибки.

START TRANSACTION;

Начало транзакции.

UPDATE postiaadress 
SET linn = uus_linn 
WHERE id = post_id AND aadress = post_aadress;

Обновляем таблицу postiaadress:

Обновляет поле linn (город) на новое значение uus_linn.

Только если:

  • id совпадает с переданным параметром post_id;
  • aadress совпадает с переданным параметром post_aadress.
UPDATE fuusiline_aadress 
SET linn = uus_linn 
WHERE id = fuus_id;

Обновляется поле linn в таблице fuusiline_aadress, где id равен fuus_id.

COMMIT;

Подтверждаем транзакцию:

Все изменения, сделанные выше, окончательно сохраняются в базе.

Короткое обьяснение:

КомандаЧто делает
DECLARE handlerОбработка ошибок
ROLLBACKОтмена транзакции при ошибке
START TRANSACTIONНачало изменений
UPDATEИзменяет данные в таблицах
COMMITПодтверждает все изменения
SELECT ...Выводит статус (успех или отмена)

Вызываем процедуру:

Как бы да изменилось, но еще раз вывываем процедуру, но с SELECT, чтобы сразу видить изменения в двух таблицах

Теперь попробуем вызвать, чтобы случился ROLLBACK (я не меняла сейчас процедуру, но при вызове ее я хочу привыпить в linn больше чем 15 символов)

ПЛОХО все вышло и данные записаны, ищу ошибку

В моем случаи вместо ошибки, вышло предупреждение и обрезало строчку до 15 символов

Мне нужно теоритически, чтобы при обрезке строки происходила ошибка, добавь в сессию этот параметр:

SET sql_mode = 'STRICT_ALL_TABLES';

Тогда:

  • MySQL не будет обрезать строку
  • Произойтет ошибку Data too long,
  • ROLLBACK в процедуре сработает

И после к сожалению ROLLBACK не сработал, но выдал ошибку и жалуется, что прываешт количество символов