Что происходит при отмене запроса к базе данных с использованием CancellationToken?

Ответ

Когда запрос к БД отменяется через CancellationToken, поведение зависит от драйвера базы данных (поставщика данных). В современных драйверах (например, Microsoft.Data.SqlClient для SQL Server) это приводит к попытке отменить выполнение команды на самом сервере БД.

Типичный сценарий:

  1. Драйвер отправляет специальный TDS-пакет (Tabular Data Stream) для отмены выполнения текущей команды на SQL Server.
  2. Сервер БД пытается прервать выполнение запроса. Это не всегда мгновенно, особенно для сложных операций.
  3. На стороне кода приложения выбрасывается исключение (например, SqlException с определенным кодом ошибки).

Пример кода:

using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5)); // Таймаут 5 сек.
try
{
    var result = await connection.QueryAsync<MyEntity>(
        "SELECT * FROM LargeTable",
        cancellationToken: cts.Token // Токен передается в драйвер
    );
}
catch (SqlException ex) when (ex.Number == 3980) // Код ошибки "Operation cancelled"
{
    // Запрос был отменен
    _logger.LogWarning("Запрос к БД был отменен.");
}

Важные нюансы:

  • Не мгновенно: Отмена на сервере БД — это запрос, а не команда. Длительная транзакция может завершиться раньше, чем будет обработан сигнал отмены.
  • Поддержка драйверов: Не все драйверы или старые версии поддерживают корректную отмену. Всегда проверяйте документацию.
  • Соединение: Само подключение к БД обычно не разрывается и может использоваться для последующих запросов.

Ответ 18+ 🔞

А вот это, блядь, интересная тема про отмену запросов к базе данных! Сидишь ты такой, ждёшь, когда запрос выполнится, а он, сука, как будто в прорубь провалился — ни ответа ни привета. И тут ты такой: «А пошёл ты нахуй со своим запросом!» — и жмёшь Cancel.

Так вот, когда ты кидаешь этот CancellationToken в драйвер, начинается магия. Современные драйверы, типа Microsoft.Data.SqlClient для SQL Server, они не просто в соплях ждут — они реально пытаются донести твоё «пошёл нахуй» до самого сервера.

Как это примерно работает:

  1. Драйвер берёт и шлёт специальный служебный пакетик на сервер, типа: «Эй, сервак, отмени нахуй вот эту команду, которую я только что слал!»
  2. Сервер базы получает сигнал и пытается прибить запрос. Но это, блядь, не всегда сиюминутно! Если запрос уже залез глубоко в транзакцию или там хуёво-маё какие-то вычисления делает, он может и не сразу сдохнуть.
  3. У нас в коде, естественно, вылетает исключение. Не просто так, а с кодом ошибки, чтобы ты понимал, что это именно отмена, а не что-то другое.

Вот смотри, как в коде это выглядит:

using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5)); // Даём 5 секунд, и хватит!
try
{
    var result = await connection.QueryAsync<MyEntity>(
        "SELECT * FROM LargeTable", // А таблица-то, блядь, на миллион строк!
        cancellationToken: cts.Token // Подсовываем наш токен отмены
    );
}
catch (SqlException ex) when (ex.Number == 3980) // Поймали конкретную ошибку "Операция отменена"
{
    // Ну всё, приплыли. Запрос послали нахуй.
    _logger.LogWarning("Запрос к БД был отменён, потому что заебал ждать.");
}

Но есть, сука, важные моменты, которые надо понимать:

  • Это не волшебная палочка. Отмена на сервере — это вежливая просьба, а не приказ. Сервер может сказать: «Подожди, ща закончу» и только потом отменить. Особенно если запрос уже в процессе.
  • Не все драйверы одинаково полезны. Старые или левые драйверы могут проигнорировать твой токен и просто продолжать жрать ресурсы. Всегда смотри документацию, что твой драйвер умеет.
  • Соединение живое. Само подключение к базе обычно не умирает. Его можно использовать дальше для других запросов. Убили только один долбоёбский запрос, а не всю сессию.

Короче, инструмент полезный, но не всесильный. Как говорится, доверия — ноль, всегда проверяй, что у тебя там на самом деле происходит.