[БД] проблема корректности (актуальности) данных
в случае запроса метить товар галочкой на предмет того, что его возможно купят и в течении 10 минут не показывать наличие этого товара.
Второй подход (оптимистическая блокировка) - совершенно нормален во многих случаях. Да в 1% случаев пользователь, который 40 минут медитировал над списком товаров, при коммите транзакции уровня приложения получит сообщение "К сожалению товар ХХХ уже распродан". Ну что тут поделаешь? А лочить там чего-то (пессимистическая блокировка) - это неправильно. Я не говорю, что п. б. совсем никогда не нужна, но она явно не для данного случая. Уровень параллельности будет очень низкий.
Не очень понял, что ты имел в виду. Мне бы простыми словами
![](/images/graemlins/blush.gif)
С первым подходом мне всё более-менее понятно. Мне он не нравится тем, что если интерфейс достаточно сложный, то в нём может быть трудно адекватно отреагировать на такую ситуацию. Или, например, начали мы какую-то длительную, но не атомарную операцию (например, хотим экспортировать из базы все счета, выставленные на данный товар а в её середине товар взял и исчез. Что тут пользователю скажешь?
>Я не говорю, что п. б. совсем никогда не нужна, но она явно не для данного случая. Уровень параллельности будет очень низкий.
А если все пользователи в основном читают данные, а удаления происходят редко + могут ждать сколь угодно долго, то вроде не так уж и плохо получается. Меня в нём скорее пугают технические проблемы. Например, какие механизмы использовать для блокирования? Делать транзакции, внутри которых будет запускаться гуйня - везде пишут, что так не положено (кстати, почему?). Или курсоры (рекордсеты) создавать, но с ними вообще всё как-то невнятно - что они, как и на какое время блокируют.
>при коммите транзакции уровня приложенияНу имелось в виду, что есть транзации у СУБД и есть транзакции у приложения. Часто они отображаются "один в один", но не всегда. Вот в случае с оптимистической блокировкой, транзакция приложения начинается, когда пользователю выведен список товаров, заканчивается, когда пользователь выбрал товары, которые он хочет купить и они, скажем, добавлены в заказ. А с точки зрения СУБД при этом транзакций две и обе короткие. В первой мы читаем список товаров. Во второй выбраные товары добавляем заказ. Вот при добавлении в заказ мы можем обнаружить, что какой-то товар удален и транзакцию придется откатить. Это произойдет как на уровне СУБД, так и на уровне приложения (товар-то выбранный не будет добавлен в заказ).
Не очень понял, что ты имел в виду. Мне бы простыми словами
Или, например, начали мы какую-то длительную, но не атомарную операцию (например, хотим экспортировать из базы все счета, выставленные на данный товар а в её середине товар взял и исчез. Что тут пользователю скажешь?Суть операции можно подробнее объяснить? Я не понимаю, видимо, товар закончился или удалили запись о нем? С удалением инфы в таких случаях вообще надо осторожно. Лучше флажок заводить "удален". И читающию транзакцию делать на уровне изоляции snapshot, тогда, даже если флажок посреди транзакции будет перброшен в состояние "удалено", на читающей транзакции это не отразится.
А если все пользователи в основном читают данные, а удаления происходят редко + могут ждать сколь угодно долго, то вроде не так уж и плохо получается.Если все как ты сказал, то неплохо да. Я просто несколько не так себе ситуацию представлял.
Например, какие механизмы использовать для блокирования?Зависит от используемой СУБД. Очень неконкретно можно сказать так: уровни изоляции транзакций + специфичные для разных СУБД команды, накладывающие блокировки на записи/таблицы. В общем поконкретнее сформулируй вопрос и кто-то тебе может быть ответит на него конкретно.
![](/images/graemlins/smile.gif)
1 - остатки товаров,
2 - список номенклатуры.
При сохранении заказа проверять наличие нужного количества на остатках, если нет, то не сохранять заказ, сообщение о нехватке пользователю.
в общем случае, просто ловим ошибку и пользователю выдаем красивое сообщение о том, что товар уже был продан, удален из списка номенклатуры и т.д.
Выбор между пессимистическими и оптимистическими блокировкам сильно зависит от степени конкурентности и требований к поведению системы. Соответственно выбор ты должен сделать сам.
Оставить комментарий
Josy
Родился у меня очередной дилетантский вопрос. Рассмотрим следующий простой пример.Пусть имеется таблица в базе данных, содержащая, скажем, записи о товарах. В некоторый момент делается селект из этой таблицы, и список показывается в интерфейсе пользователя - например, в форме оформления заказа. Пользователь выбирает какой-то товар, жмёт ОК, и с ним делаются какие-то там действия. Но предположим, что за то время, пока пользователь думал, чего выбрать, запись в базе, соответствующая выбранной им в итоге строчке, была каким-либо образом удалена (например, другим пользователем). В результате приложение пытается доступиться к несуществующим данным, и приехали.
Вопрос, собственно - Как можно бороться с подобными ситуациями, и как с ними борются в реальных приложениях?
Какие я вижу альтернативы:
1) Каким-либо способом блокировать нужные данные. Но как-то мне кажется, что необходимая в данном примере блокировка всей таблицы - это очень жёстко, и в случае, если зависимых таблиц несколько, дедлоков будет избежать очень трудно.
2) Любой код, оперирующий данными в базе должен, прежде, чем предпринять какие-то действия, всегда проверять, а не протухли ли нужные данные / связанные с ними данные и т.д. (Причём внутри транзакции). Тоже как-то безрадостно.
В общем - "что делать?" (с)