BEGIN, COMMIT, ROLLBACK
Накратко: BEGIN започва транзакция, COMMIT записва промените ѝ, ROLLBACK ги отменя, а SAVEPOINT слага точка, до която ROLLBACK TO отменя само част от тях.
Проблем
Грешката, след която нищо не е свършило
Програмата вдига цените на млечните с 10% и в същата транзакция поправя цената на хляба. Във втората заявка има грешка: цената става отрицателна. Пусни:
Втората заявка спря. А първата? Поскъпването на млечните отменено ли е, или е влязло?
Идеята
Транзакцията остава отворена
Нито едното. SQLite отменя само заявката с грешката. Транзакцията остава отворена, а поскъпването на млечните е в нея, още непотвърдено.
Пробвай в същото поле, без „Нова база“. Изтрий текста, напиши SELECT name, price FROM products WHERE category_id = 4; и пусни: цените са вдигнати. После напиши ROLLBACK; и пусни заявката за цените пак.
Затова програмата, която работи с транзакции, винаги има два пътя: всичко е наред, значи COMMIT; нещо спря, значи ROLLBACK. Ако не каже нищо, транзакцията виси. Докато виси, в SQLite никой друг не може да пише в базата, а в PostgreSQL и MySQL чакат всички, които искат да променят същите редове.
По-точно, за любопитните
Ако в това поле пуснеш BEGIN пак, без да си затворил старата транзакция, SQLite казва „cannot start a transaction within a transaction“. В PostgreSQL е по-строго: след грешка цялата транзакция е развалена, и до ROLLBACK всяка следваща заявка отказва да се изпълни.
Виж го
Какво виждам вътре
Вътре в транзакцията промените се виждат, преди да са потвърдени, но само от нея:
Друга връзка към базата (друг потребител, друга програма) още вижда старите цени. Ще видим двете сесии една до друга в следващия урок.
Идеята
SAVEPOINT: връщане до точка
Понякога искаш да се откажеш само от част от транзакцията. SAVEPOINT име слага точка, а ROLLBACK TO име връща до нея. Всичко преди точката остава, и транзакцията продължава.
Доставка: хлябът е пристигнал (+10), напитките още не. Те се добавят по навик, после се връщат:
Хлябът е с 10 повече, напитките са непроменени.
Упражнение
Само хлябът поскъпва
Транзакцията вдига с 5% цените на хляба и на млечните. Шефът казва, че млечните остават със старите цени. Добави един ред, така че да се отмени само поскъпването на млечните.
Решение
BEGIN;
UPDATE products SET price = ROUND(price * 1.05, 2) WHERE category_id = 3;
SAVEPOINT dairy;
UPDATE products SET price = ROUND(price * 1.05, 2) WHERE category_id = 4;
ROLLBACK TO dairy;
COMMIT;
SELECT name, price FROM products WHERE category_id IN (3, 4);ROLLBACK TO dairy; на мястото на коментара. Хлябът е по-скъп, млечните са със старите цени, а транзакцията завършва с COMMIT.
Тест
Провери се
Свързани уроци
Раздел „Свързани уроци“- Нужно отпреди: Сметки в заявката · UPDATE: промяна на редове · ACID: всичко или нищо
- Продължава в: Едновременни транзакции · Миграции на схемата · OLTP и OLAP · Как се избира база
- Задачи по темата: Транзакции