Перейти к содержимому

Первые транзакции: BEGIN, COMMIT, ROLLBACK

Курс MS SQL с нуля · Урок 11 из 12 · Часть 4. Запросы как инструмент

Транзакция — договор «всё или ничего»: пакет изменений либо записывается целиком, либо откатывается без следа. Урок безопасной глубины: ручной контроль в одной консоли, откат как привычка.

Внимание: урок меняет данные TechStore и работает в режиме Tx: Manual. Конец занятия — с @@TRANCOUNT в нуле и пересозданием базы скриптами урока 2. Гонки сеансов оставлены продвинутому курсу.

Содержание

1. Что вы освоите

К концу урока вы:

  • объявляете пакет изменений атомарным через BEGIN TRAN и COMMIT;
  • откатываете цепочку целиком ROLLBACK-ом и знаете его грубость;
  • работаете в режиме Tx: Manual в DataGrip осознанно;
  • сверяете @@ROWCOUNT и @@TRANCOUNT как приборы консоли;
  • наблюдаете блокировку вторым сеансом и объясняете её механику.
↑ К оглавлению

2. BEGIN TRAN, COMMIT, ROLLBACK

Чистый код

BEGIN TRAN;

UPDATE p SET StockQty = StockQty - 1
FROM dbo.Products AS p
WHERE p.ProductID = 42;

SELECT StockQty FROM dbo.Products WHERE ProductID = 42;

COMMIT;
SQL
  • Построчный разбор

    Ниже приведён тот же фрагмент с пояснением после каждой смысловой строки. Строки, которые начинаются с двух дефисов и стрелки вправо, содержат комментарий преподавателя. Эти строки не являются обязательной частью программы.

    BEGIN TRAN;
    -- → транзакцию открывают до первого изменения, не после
    
    UPDATE p SET StockQty = StockQty - 1
    FROM dbo.Products AS p
    WHERE p.ProductID = 42;
    -- → списание одного остатка; пока видимо только этому сеансу
    
    SELECT StockQty FROM dbo.Products WHERE ProductID = 42;
    -- → взгляд до COMMIT: состояние проверяется глазами
    
    COMMIT;
    -- → записать навсегда; альтернатива — ROLLBACK, отменить целиком;
    -- → оба оператора сразу недопустимы: Msg 3903
    SQL
  • пока транзакция открыта, изменение видно лишь своему сеансу: другие видят старые значения — простейшая демонстрация изоляции;
  • @@TRANCOUNT — число открытых транзакций сеанса; после COMMIT и ROLLBACK — ноль;
  • забытая открытая транзакция держит блокировки — механика «всё повисло» другой консоли.
Операторная атомарность не бесплатна для пакетов: один оператор сервер завершает целиком либо никак и сам. Но платёж плюс смена статуса — уже пакет из двух операторов, и его половинчатость защищается только явной транзакцией.
↑ К оглавлению

3. Режим Tx в DataGrip

На верхней панели консоли DataGrip — переключатель Tx: Auto или Manual. В Auto каждый оператор — самодостаточная микротранзакция с автоподтверждением; в Manual операторы накапливаются, пока не нажмёте зелёную галочку Commit или красный крест Rollback.

Режим лабораторий урока

Manual и только он

Все задачи урока выполняются в Tx: Manual: это единственный способ откатить уже выполненный UPDATE взглядом на панели. Перед началом переключатель проверяется глазами, а в конце занятия возвращается в Auto вместе с проверкой @@TRANCOUNT = 0.

Вложенность и грубость ROLLBACK

Чистый код

BEGIN TRAN;
SELECT @@TRANCOUNT AS depth1;
BEGIN TRAN;
SELECT @@TRANCOUNT AS depth2;
COMMIT;
SELECT @@TRANCOUNT AS depth3;
ROLLBACK;
SELECT @@TRANCOUNT AS depth4;
GO
SQL
  • Построчный разбор

    Ниже приведён тот же фрагмент с пояснением после каждой смысловой строки. Строки, которые начинаются с двух дефисов и стрелки вправо, содержат комментарий преподавателя. Эти строки не являются обязательной частью программы.

    BEGIN TRAN;
    SELECT @@TRANCOUNT AS depth1;
    -- → глубина один: первый BEGIN открыл цепочку
    BEGIN TRAN;
    SELECT @@TRANCOUNT AS depth2;
    -- → глубина два: вложенный BEGIN лишь наращивает счётчик
    COMMIT;
    SELECT @@TRANCOUNT AS depth3;
    -- → COMMIT уменьшил счётчик до единицы: цепочка жива
    ROLLBACK;
    SELECT @@TRANCOUNT AS depth4;
    -- → ROLLBACK гасит всю цепочку разом, счётчик в нуле
    GO
    SQL

Вывод лаборатории: COMMIT уменьшает счётчик на единицу, а ROLLBACK сводит цепь целиком к нулю: вложенные COMMIT безопасны, вложенные ROLLBACK — грубые. Точечный возврат внутри пакета — SAVE TRAN — тема продвинутого урока.

↑ К оглавлению

4. Перестраховочный паттерн

Перестраховочный паттерн массового изменения из четырёх шагов:

  1. SELECT с предикатом — считает и показывает строки цели;
  2. BEGIN TRAN и UPDATE тем же предикатом; сверка @@ROWCOUNT с прогнозом;
  3. взгляд на выборку после изменения;
  4. COMMIT только когда три числа сошлись; иначе ROLLBACK.
Где практика паттерна: задача 11.1 собирает покупку товара атомарным пакетом: уменьшение остатка и вставка строки заказа подтверждаются одним COMMIT; отдельные подтверждения половинчатости не защищают.
↑ К оглавлению

5. Задачи и эталонные решения

Шесть задач на контексте TechStore, все — в одной консоли с Tx: Manual. Вторая консоль понадобится с задачи 11.5.

  1. покупка товара атомарным пакетом: остаток минус один плюс строка заказа, один COMMIT в конце;
  2. намеренный откат: категория 5 дешевеет на девяносто процентов, осмотр, ROLLBACK; в журнал комментариями — @@ROWCOUNT и @@TRANCOUNT;
  3. двойной COMMIT: вторая попытка падает с Msg 3902, номер записывается в журнал;
  4. лаборатория вложенности: два BEGIN подряд, счётчики, единый ROLLBACK и вывод;
  5. взгляд извне: пока первая консоль держит изменение открытым, вторая читает те же строки; наблюдения записываются;
  6. зависшая песочница: первая консоль «забыла» транзакцию, вторая меняет ту же строку, пять секунд ожидания, стоп, откат первой.

Эталон задачи 11.1

пакет подтверждается одним COMMIT

Чистый код

BEGIN TRAN;

UPDATE p SET StockQty = StockQty - 1
FROM dbo.Products AS p
WHERE p.ProductID = 42;

INSERT dbo.OrderItems (OrderID, ProductID, Quantity, UnitPrice)
SELECT (SELECT MAX(x.OrderID) FROM dbo.Orders AS x), 42, 1, p.Price
FROM dbo.Products AS p
WHERE p.ProductID = 42;

SELECT StockQty FROM dbo.Products WHERE ProductID = 42;

COMMIT;
GO
атомарность пакета
  • Построчный разбор

    Ниже приведён тот же фрагмент с пояснением после каждой смысловой строки. Строки, которые начинаются с двух дефисов и стрелки вправо, содержат комментарий преподавателя. Эти строки не являются обязательной частью программы.

    BEGIN TRAN;
    -- → пакет из двух изменений становится атомарным
    
    UPDATE p SET StockQty = StockQty - 1
    FROM dbo.Products AS p
    WHERE p.ProductID = 42;
    -- → первый шаг: списание остатка
    
    INSERT dbo.OrderItems (OrderID, ProductID, Quantity, UnitPrice)
    SELECT (SELECT MAX(x.OrderID) FROM dbo.Orders AS x), 42, 1, p.Price
    FROM dbo.Products AS p
    WHERE p.ProductID = 42;
    -- → второй шаг: учебная позиция в последний заказ по цене каталога
    
    SELECT StockQty FROM dbo.Products WHERE ProductID = 42;
    -- → сверка глазами: сошлось, подтверждаем; не сошлось — ROLLBACK
    
    COMMIT;
    GO
    атомарность пакета
↑ К оглавлению

6. Типичные ошибки урока

  1. BEGIN после UPDATE — транзакция началась после изменения; изменение прошло мимо неё. BEGIN ставится первым.
  2. ROLLBACK после COMMIT — Msg 3903: транзакцию завершают один раз и осмысленно.
  3. Auto-режим в лаборатории — изменение подтвердилось само; переключатель Tx проверяется взглядом до начала.
  4. Открытая транзакция на ночь — цепочка блокировок в боевой базе; правило курса: конец лаборатории — проверка @@TRANCOUNT = 0.
  5. ROWCOUNT на глазах — «выглядит правдоподобно» не приём; число сравнивается с прогнозом SELECT вслух.
  6. ROLLBACK якобы на один шаг — ROLLBACK гасит всю цепочку; точечный возврат — SAVE TRAN, тема продвинутого курса.
↑ К оглавлению

7. Чек-лист практики и источники

Чек-лист урока 11

отметки делаются по факту

Источники для углубления:

  1. BEGIN TRANSACTION: семантика счётчика;
  2. COMMIT и ROLLBACK;
  3. Руководство по блокировкам: первые главы.
Итог: изменения вручную безопасны и обратимы. Урок 12 — финальный: первый план запроса и первый индекс, мост к продвинутому курсу.

Проверено: 23.10.2026

↑ К оглавлению
Конспект:
Четверг, 22 октября 2026