Skip to content

32. Неблагоприятные эффекты, вызванные параллельным выполнением транзакций, и их устранение

Pandas edited this page Jan 2, 2018 · 1 revision

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

Потерянные обновления

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

Незафиксированная зависимость («грязное» чтение)

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

Анализ несогласованности (неповторяющееся чтение)

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

Фантомные операции чтения

Чтение фантомных данных — это ситуация, которая возникает при выполнении двух идентичных запросов, если набор строк, возвращаемых вторым запросом, отличается от первого. Предположим, что две транзакции выполняются одновременно. Две инструкции SELECT в первой транзакции могут возвращать разные результаты, поскольку инструкция INSERT во второй транзакции изменяет данные, используемые обеими этими инструкциями.

// Transaction 1
SELECT * FROM dbo.employee ...
// Transaction 2
SELECT * FROM dbo.employee COMMIT
// Transaction 2
INSERT INTO dbo.employee SET name = 'BBB' WHERE id = 5

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

Исчезновение обновленной строки или ее многократное отображение Транзакции, работающие на уровне изоляции READ UNCOMMITTED, не используют совмещаемые блокировки, чтобы предотвратить изменение считываемых текущей транзакцией данных другими транзакциями. Транзакции, работающие на уровне изоляции READ COMMITTED, используют совмещаемые блокировки, однако блокировки строк и страниц снимаются после чтения строки. В любом случае, если во время сканирования индекса другой пользователь изменит ключевой столбец индекса для строки, считывание которой происходит в данный момент, причем строка была перемещена в позицию, до которой операция сканирования еще не дошла, эта строка может появиться повторно. Аналогично, если изменение ключа переместило строку в позицию, считывание которой уже прошло, то она может не отобразиться. Чтобы избежать этого, воспользуйтесь указаниями SERIALIZABLE или HOLDLOCK либо управлением версиями строк.

Отсутствие одной или нескольких строк, которые не подвергались обновлению

Пропажа строк может возникнуть в случае, если при использовании уровня READ UNCOMMITTED запрос читает строки в порядке их расположения (с использованием IAM-страниц), а другая транзакция вызывает разбиение страницы. Этого не может произойти при использовании уровня изоляции READ COMMITTED, поскольку во время разбиения страницы включается блокировка таблицы.Также этого не может произойти, если таблица не имеет кластеризованного индекса, поскольку в таком случае обновления не вызывают разбиения страниц.

Clone this wiki locally