Проблемы параллельного доступа.
При параллельном использовании транзакций могут возникать следующие проблемы:
- потерянное обновление (lost update);
- "грязное" чтение (dirty read);
- неповторяющееся чтение (non-repeatable read);
- фантомная вставка(phantom insert).
1. Потерянное обновление может возникнуть в ситуации, когда две транзакции обновляют одни и те же данные.
Предположим, происходит одновременная работа с таблицей ShopTable. Две транзакции открыты различными приложениями.
Транзакция 1 | Транзакция 2 | Cost |
SELECT Сost FROM ShopTable WHERE PrName = ‘CD-R’; UPDATE ShopTable SET Сost = Сost*2 WHERE PrName = ‘CD-R’; | SELECT Сost FROM ShopTable WHERE PrName = ‘CD-R’; UPDATE ShopTable SET Сost = Сost*2 WHERE PrName = ‘CD-R’; |
В транзакции 1 изменяется значение поля Cost, а затем в транзакции 2 также изменяется значение этого поля. В результате изменение, выполненное второй транзакцией, сделает результат неожиданным. Пусть начальное значение Cost = 50, тогда транзакция 1 изменит его на Cost = 100, после чего транзакция 2 увеличит значение поля ещё в два раза, в итоге Cost = 200.
2. «Грязное» чтение возникает, когда вторая транзакция видит не сохранённые изменения, сделанные первой транзакцией, после чего происходит откат первой транзакции.
Транзакция 1 | Транзакция 2 | BookName |
SELECT BookName FROM Books WHERE SerialNum = “1234”; UPDATE Books SET BookName = “Азбука” WHERE SerialNum = “1234”; ROLLBACK WORK; | SELECT BookName FROM Books WHERE SerialNum = “1234”; | “Обломов” “Азбука” “Азбука” “Обломов” |
В транзакции 1 изменяется значение поля Cost, а затем транзакция 2 выбирает значение этого поля. После этого происходит откат транзакции 1. В результате значение, полученное второй транзакцией, будет отличаться от реального значения, хранимого в базе данных.
3. Неповторяющееся чтение – это ситуация, когда в рамках одной транзакции один и тот же запрос возвращает разные результаты.
Транзакция 1 | Транзакция 2 | Balance |
SELECT Balance FROM BTable WHERE UserID = 1; UPDATE BTable SET Balance = Balance - 1000 WHERE UserID = 1; | SELECT Balance FROM BTable WHERE UserID = 1; SELECT Balance FROM BTable WHERE UserID = 1; |
В транзакции 2 выбирается значение поля Balance, это значение используется для расчетов. В это время транзакция 1 изменяет поля Balance. При повторной попытке выбора значения из поля Balance в транзакции 2 будет получен другой результат. Пример: считывается информация о состоянии счета клиента банка, проверяется, достаточно ли средств на счету для выполнения какой-либо операции. В это время другая транзакция переводит деньги на другой счет. Следовательно, данные первой транзакции являются ошибочными, при повторном считывании данных будет получен другой результат, операцию проводить нельзя.
4. Фантомная вставка – частный случай неповторяющегося чтения – заключается в том, что результаты одной и той же выборки в рамках одной транзакции имеют разное количество возвращаемых строк.
Транзакция 1 | Транзакция 2 | |
INSERT ShopTable (PrName, Cost) VALUES (rake, 1000); | SELECT AVG(Cost) FROM ShopTable; SELECT AVG(Cost) FROM ShopTable; |
В транзакции 2 выполняется запрос, использующий все значения поля cost. Затем транзакция 1 выполняет вставку новой строки, после этого повторное выполнение запроса в транзакции 2 выдаст другой результат.
При этом, если выполняемый запрос выбирает не все значения поля cost, а значение только одной строки таблицы, то выполнение оператора INSERT не приведет к ситуации фантомной вставки.
Дата добавления: 2018-09-24; просмотров: 649;