Задать вопрос

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

1) статья на википедии:
https://ru.wikipedia.org/wiki/%D0%A3%D1%80%D0%BE%D...

Потерянное обновление (lost update):
2 запроса одновременно меняют значение поля в строке таблицы
UPDATE tbl1 SET f2=f2+20 WHERE f1=1; UPDATE tbl1 SET f2=f2+25 WHERE f1=1;
В результате значение поля f2 по завершении обеих транзакций может увеличиться не на 45, а на 20 или 25, то есть одна из изменяющих данные транзакций «пропадёт».


Вопрос: учитывая, что каждый индивидуальный запрос в ms sql (и я читал, что не только в нем, а во-всех СУБД, которые поддерживают транзакции) выполняется в неявной автоматической транзакции, то с чего вдруг станет возможно "потерянное обновление"? Т.е. второй update же не сможет прочитать значение f2, пока автоматическая транзакция первого update не завершится.
Даже если предположим, что автор писал текст, предполагая отсутствие автоматических транзакций, то не понятно следующее: поскольку в ms sql автоматические транзакции точно есть, то для чего в ms sql в явных транзакциях есть поддержка уровня изоляции read uncommitted, который защищает только от "потерянных обновлений"? Ведь даже без явных транзакций итак должна быть защита от них, т.к. работают автоматические транзакции?

2) статья на хабре:
https://habrahabr.ru/company/infopulse/blog/261097/ - раздел Потерянное обновление – Интерпретация №2
он там приводит таблицу, в которой 2 параллельных update апдейтят одно и то же поле в БД аналогично тому, как было в статье в википедии. Но у автора на хабре оба запроса заключены в транзакции BEGIN TRAN; COMMIT TRAN; , но в результате он пишет, что произойдет "потерянное обновление".

Вопрос: как может произойти потерянное обновление, если оба его запроса выполняются каждый внутри своей транзакции?
  • Вопрос задан
  • 581 просмотр
Подписаться 4 Оценить Комментировать
Пригласить эксперта
Ответы на вопрос 2
terrier
@terrier
Вы, похоже, не совсем понимаете, суть понятия "транзакция". Оно означает только то, что логическая группа операций либо выполнится полностью, либо полностью откатится. Что "увидят" соседние транзакции в процессе работы конкретной транзакции - зависит именно от уровня изоляции. Может быть примерно все, включая промежуточные итоги незакоммиченной транзакции, а может быть совсем ничего
Ответ написан
asumin
@asumin
/Web/PHP
Статья на википедии имеет более глубокие исторические корни, она не про то какие сейчас есть клевые СУБД, а о том как они развивались. Т.е. когда-то давно-давно, были простейшие СУБД без транзакций, без изолированности и пользователи при их эксплуатации сталкивались с определенными ошибками: кто-то увидел чужие данные которых не было, кто-увидел фантомные данные, которых больше нет и так далее, в ответ на эти проблемы появлялись более строгие уровни изоляции данных. При этом есть дилемма: чем выше уровень изоляции - тем ниже производительность системы. Т.е. это статья больше о теории хранения данных с совместным доступом, например, с какими проблемами вы столкнетесь, если захотите написать свой транзакционный движок.

Теперь про потерянное обновление, есть таблица Counter с одной строкой и полем count = 0.
Транзакция №1
UPDATE counter SET count = count + 10;
что в это время делает движок:
1. читает текущее значение count равное 0
2. прибавляет к нему 10
3. но транзакция еще не завершена, и новое значение 10 просто держится в памяти
В это время стартует Транзакция №2 с тем же самым запросом
UPDATE counter SET count = count + 10;
что делает движок? То же самое что и в первый раз:
1. читает текущее значение count равное 0, потому что первая транзакция еще не завершена, и вторая не видит её результатов <- это и есть уровень изоляции, мы или видим данные в чужой транзакции или нет.
2. прибавляет к нему 10
3. завершаем Транзакцию №2 и на диск сохраняется count равное 10.
После этого подоспела и первая транзакция, она тоже готова сохранить своё вычисленное значение count равное 10 и на диск снова пишется 10, а не 20, как мы ожидали.

Современные промышленные СУБД такой трюк провести не дадут (строки на время update будут заблокированы), а вот студент, который пишет программу для курсовой работы, может допустить такую не очевидную ошибку.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы