Описание конкурентности

Завершено

Основная функция многопользовательских баз данных — параллелизм. Конкурентность использует блокировку и блокирование для обеспечения согласованности данных, когда множество пользователей обновляют и считывают данные одновременно. Например, из-за затрат на доставку все наши товары имеют увеличение цены на $5. В то же время из-за курсов валют все продукты подвержены уменьшению цен на 3%. Если эти обновления происходят точно в то же время, окончательная цена будет переменной, и вероятно, будет много ошибок. С помощью блокировки можно убедиться, что одно обновление завершится до начала другого.

Одновременность происходит на транзакционном уровне. Транзакция записи может блокировать другие транзакции от обновления и даже чтения одних и того же данных. В равной степени транзакция чтения может блокировать другие читатели или даже некоторые записи. По этой причине важно избежать слишком длинных транзакций или транзакций, охватывающих чрезмерные объемы данных.

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

Замечание

Полная детализация блокировки транзакций за пределами параллелизма связана с производительностью и не только зависит от кода, хотя хороший код работает лучше. Дополнительные сведения см. в подробном руководстве по блокировке транзакций SQL Server и настройке версий строк . Дополнительные сведения о блокировке см. в документации по производительности SQL Server.

Оптимистическая конкуренция

При оптимистической блокировке предполагается, что возникновение конфликтующих обновлений будет редким. В начале транзакции записывается начальное состояние данных. Перед фиксацией транзакции текущее состояние сравнивается с начальным состоянием. Если статусы совпадают, транзакция завершается. Если состояния отличаются, транзакция будет отменена.

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

Пессимистичный параллелизм

При пессимистической блокировке существует предположение, что многие обновления происходят с данными одновременно. При использовании блокировок одновременно может произойти только одно обновление, а чтение данных предотвращается во время выполнения обновлений. Это может предотвратить большие откаты, как показано в предыдущем примере, но может привести к ненужной блокировке запросов.

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

Изоляция снимка

Существует пять разных уровней изоляции в SQL Server, но для этого модуля мы сосредоточимся только на READ_COMMITTED_SNAPSHOT_OFF и READ_COMMITTED_SNAPSHOT_ON. READ_COMMITTED_SNAPSHOT_OFF — это уровень изоляции по умолчанию для Microsoft SQL Server. READ_COMMITTED_SNAPSHOT_ON — это уровень изоляции по умолчанию для базы данных SQL Azure.

READ_COMMITTED_SNAPSHOT_OFF будет хранить блокировки на затронутых строках до конца транзакции, если запрос использует уровень изоляции зафиксированных транзакций с чтением. Хотя некоторые обновления могут произойти, например создание новой строки, это позволит предотвратить большинство конфликтующих изменений в данных, которые будут считываться или обновляться. Это пессимистичная конкуренция.

READ_COMMITTED_SNAPSHOT_ON создает моментальный снимок данных. Затем обновления выполняются на этом снимке состояния, позволяя другим подключениям запрашивать исходные данные. В конце транзакции текущее состояние данных сравнивается с моментальным снимком. Если данные одинаковы, транзакция фиксируется. Если данные отличаются, транзакция откатится.

Чтобы изменить уровень изоляции на READ_COMMITTED_SNAPSHOT_ON, выполните следующую команду:

ALTER DATABASE *db_name* SET READ_COMMITTED_SNAPSHOT ON;

Чтобы изменить уровень изоляции на READ_COMMITTED_SNAPSHOT_OFF, выполните следующую команду:

ALTER DATABASE *db_name* SET READ_COMMITTED_SNAPSHOT OFF;

Если база данных была изменена, чтобы включить зафиксированный моментальный снимок для чтения, любая транзакция, использующая уровень изоляции фиксации чтения по умолчанию, будет использовать оптимистическую блокировку.

Замечание

Изоляция моментальных снимков выполняется только для транзакций, зафиксированных для чтения. Транзакции, использующие другие уровни изоляции, не затрагиваются.