Обсуждение:Уровень изолированности транзакций

message: Согласно этого определения
 
Repeatable read (повторяемость чтения)
Уровень, при котором чтение одной и той же строки или строк в транзакции дает одинаковый результат. (Пока транзакция не завершена, никакие другие транзакции не могут модифицировать эти данные.)
нужно дополнить, что возможно добаление строк, и один и тот же Select может вернуть разный результат. 
REPEATABLE READ
All data records read by a SELECT statement cannot be changed; however, if the SELECT statement contains any ranged WHERE clauses, phantom reads can occur. In this isolation level, the transaction acquires read locks on all retrieved data, but does not acquire range locks.

message: Если идти по ссылке [3] (из главы "Поведение при различных уровнях изолированности") Understanding Isolation Levels то там написано довольно однозначно:
replies: text: Transactions must be run at an isolation level of at least repeatable read to prevent lost updates that can occur when two transactions each retrieve the same row, and then later update the row based on the originally retrieved values.
Что противоречит главе "Потерянное обновление", где совершенно не указано никаких переменных (SET f2=f2+20) и SELECT не играет никакой роли.
Данный "феномен" можно интерпретировать тремя способами, два из которых описаны в Understanding the Available Transaction Isolation Levels:

text: Lost Update

text: A lost update can be interpreted in one of two ways. In the first scenario, a lost update is considered to have taken place when data that has been updated by one transaction is overwritten by another transaction, before the first transaction is either committed or rolled back. This type of lost update cannot occur in SQL Server 2005 because it is not allowed under any transaction isolation level.

text: The other interpretation of a lost update is when one transaction (Transaction #1) reads data into its local memory, and then another transaction (Transaction #2) changes this data and commits its change. After this, Transaction #1 updates the same data based on what it read into memory before Transaction #2 was executed. In this case, the update performed by Transaction #2 can be considered a lost update.
Согласно этому источнику надо исправить таблицу "Поведение при различных уровнях изолированности"
Уровень изоляции	Фантомная вставка	Неповторяющееся чтение	«Грязное» чтение	Потерянное обновление
SERIALIZABLE    	+                	+                     	+               	+
REPEATABLE READ 	–                	+                     	+               	+
READ COMMITTED  	–                	–                     	+               	[-]
READ UNCOMMITTED	–                	–                     	–               	[-]
Но ещё существует и режим Snapshot isolation (глава Serializable Snapshot Isolation), кстати совсем не освещённые в данном документе, в котором можно сказать что (SET f2=f2+20) даст "потерянное обновление", но такое "перекрывающее обновление" не может быть применено (COMMIT вылетит с ошибкой).
На английской вики данный "феномен" не описан, отводя читателя в правильное русло термином "Read phenomena". Ибо никаких "Write phenomena" в СУБД не допускается.
91.216.166.20 09:44, 30 августа 2012 (UTC)
* Для того, чтоб не возникало путаницы с интерпретацией термина lost update, можно вместо "Потерянное обновление" столбец назвать "разрушение данных", так как в таблицу попала первая интерпретация (изменение данных второй транзакцией, раньшне завершения первой транзакции так же изменившей эти данные). Вторая же интерпретация описывает одно из возможных последствий феномена "неповторяюшееся чтение". А теперь по порядку. Таблица описывает возможные конфликты параллельного доступа(феномены), и какие уровни изоляции какие из этих конфликтов разрешают. Разрешаются конфликты, очевидно, механизмом блокировок, так как в многоверсионных СУБД никаких грязных чтений нет.

text: Феномены и поведение блокировок при разных уровнях изоляции(в примерах, транзакция №1 читает, а транзакция №2 изменяет):

text: 1. SERIALIZABLE. При чтении данных до окончания транзакции выставляется блокировка, которая заблокирует попытку изменить данное "добавить фантом" по отношению к этому чтению. Пример: выполняется транзакция №1, с уровнем изоляции SERIALIZABLE, которая прочитала таблице "прайс" товары(строки) с ценой от 100 до 200руб. Транзакция №2, с любым! уровнем изоляции, не сможет добавить в таблицу прайс новый товар, например с ценой 120 руб, или изменить цену одного из существующих товаров (например, с 300 на 150руб), пока первая транзакция не завершится. Вариант реализации: при чтении, до окончания serializable-транзакции на всю таблицу выставляется блокировка, снятия которой будут ожидать все попытки изменения таблицы(insert/update). Результат для транзакции №1: внутри транзакции при повторном чтении не возникает "новых"(фантомных) строк.

text: 2. REPEATABLE READ + SERIALIZABLE. При чтении данных до окончания транзакции выставляется блокировка, которая заблокирует другим попытку изменить прочитанное данное. Пример: выполняется транзакция №1, с уровнем изоляции serializable или repeatable read, которая прочитала в таблице "прайс" товары(строки) с ценой от 100 до 200руб. Транзакция №2, с любым! уровнем изоляции, не сможет изменить(или удалить) строки прочитанные транзакцией №1, пока она не завершится. Вариант реализации: при чтении, до окончания serializable и repeatable read-транзакций на прочитанные строки выставляется блокировка, снятия которой будут ожидать все попытки эти строки изменить(update/delete). Результат: однажды прочитанная строка до окончания транзакции не изменится и не пропадёт.

text: 3. READ COMMITTED. Аналогично, п.2, но блокировка чтения снимается по окончании самого чтения, а не оставляется до окончания всей транзакции №1. Поэтому внутри транзакции, при повторном чтении, ранее прочитанная строка может оказаться уже изменённой или быть удалёна.

text: 4. READ UNCOMMITTED. В п.1, 2 и 3 все чтения начинаются только после!! успешной установки блокировки чтения на читаемые строки. А для транзакции с уровнем изоляции read uncommitted данные читаются без попыток установки блокировок("грязно"). Таким образм, если какая-то из строк таблицы изменяется транзакцией №2, которая ещё до конца не выполнилась, то чтение транзакцией №1 на всех уровнях изоляции(кроме read uncommitted) будут ожидать!! успешной установки блокировки чтения, т.е. ожидать окончания транзакции №2. Результат: при read uncommitted не ждём выполнения других транзакций изменения данных, но можем прочитать "некий результат" выполнения другой транзакции, которая успешно не выполнится (откатится).

text: В таблице показано поведение блокировок на разных уровнях изоляции. Наличие столбца "потерянные обновление" добавлено в неё, чтоб подчеркнуть тот факт, что даже при самом низком уровне изоляции блокировки всё равно накладываются, чтоб избежать феномена "разрушение данных". Этот феномен никогда не возникает, так как изменение данных происходит после успешного накладывания блокировки обновления, которая не ставится при наличии других блокировок. Одно транзакция ожидает завершения(коммит или роллбэк) другой. Поэтому, "разрушение данных" это гипотетичский феномен, который не возникает ни на одном из уровней.

text: Гипотетические примеры "разрушения данных" (если бы блокировка при изменении данных не накладывалась).

text: 1. Сначала транзакция №1 обновляет данные в таблице прайс уменьшая значения столбце цены на 5, в том чилсе и для строки с ценой 11. (11 - 5) = 6.

text: 2. Потом транзакция №2 делит цены пополам. В том числе и нашу строку, (6 / 2) = 3.

text: 3. Транзакция №2 завершается успешно, сохраняя в базе 3.

text: 4. Транзакция №1 признаётся неуспешной и должна быть откачена (например, в прайсе нашлась цена 1, которую на 5 уменьшить не удалось).

text: Откат транзакции №1 произвести не удаётся. Если оставить 3, то нарушится требование к атомарности транзакции №1(всё или ничего). Цена то на 5 была уменьшена. А если вернуть 11, то нарушится требование к атомарности ранее успешно выполненной транзакции №2, которая уполовинивала все цены. CRASH!

text: Вариант таблицы для поведения блокировок(в скобках феномен, если +, то побеждён и не возникает).
Уровень изоляции	Блокировать всю* читаемую таблицу до окончания транзакции (фантом)	Блокировать читаемые строки до окончания транзакции (неповторяющееся чтение)	Блокировать читаемые строки на момент чтения («грязное» чтение)	Блокировать изменяемые строки («разрушение данных»)
SERIALIZABLE    	+                                                                 	+                                                                           	+                                                              	+
REPEATABLE READ 	–                                                                 	+                                                                           	+                                                              	+
READ COMMITTED  	–                                                                 	–                                                                           	+                                                              	+
READ UNCOMMITTED	–                                                                 	–                                                                           	–                                                              	+

text: Таблицы феноменов и методов их устранения(поведение блокировок) должны быть идентичны.

text: PS. Сорри, что так длинно написано. GutorovIV 11:04, 31 августа 2012 (UTC)
thread_title:  Потерянное обновление 

message: описанный механизм с блокировками не энциколпедичен. Не все СУБД используют такую модель (например Oracle). max 09:24, 22 ноября 2012 (UTC)
* Оракл - не пуп Земли.— 91.228.54.44 14:49, 22 апреля 2021 (UTC)
** Интересно, max увидел ответ спустя ~11 лет? 82.151.107.123 08:35, 22 февраля 2023 (UTC)
thread_title:  re: Потерянное обновление