Проверка актуальности Entity перед записью
От: zelenprog  
Дата: 25.09.23 08:58
Оценка:
Добрый день!

Программа прочитала из базы данных некую сущность Entity, и показала ее пользователю для редактирования.
Пользователь долго думает, изменяет ее свойства и нажимает кнопку "Записать".

Однако, за это время эту Сущность уже могли отредактировать в БД другие пользователи.
То есть наш пользователь видит неактуальные данные, и принимает решение о редактировании и записи Сущности на основе неактуальных данных.

Как должна делать программа в таких случаях?

Должна ли программа оповещать пользователя при изменении данных Сущности в БД?
Должна ли программа проверять актуальность редактируемых свойств Сущности непосредственно перед записью в БД новых значений этих свойств?

Объясните, пожалуйста.
Re: Проверка актуальности Entity перед записью
От: · Великобритания  
Дата: 25.09.23 09:39
Оценка: +1
Здравствуйте, zelenprog, Вы писали:


Z>Как должна делать программа в таких случаях?

Разрешать конфликт — как зависит от бизнес-требований. В простейшем случае отменять изменения пользователя и просить сделать ещё раз.

Z>Должна ли программа оповещать пользователя при изменении данных Сущности в БД?

Зависит от бизнес-требований

Z>Должна ли программа проверять актуальность редактируемых свойств Сущности непосредственно перед записью в БД новых значений этих свойств?

Да, притом с ACID.

Z>Объясните, пожалуйста.

https://en.wikipedia.org/wiki/Optimistic_concurrency_control
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 25.09.2023 9:46 · . Предыдущая версия .
Re: Проверка актуальности Entity перед записью
От: bnk СССР http://unmanagedvisio.com/
Дата: 25.09.23 09:44
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>Объясните, пожалуйста.


Это не забота программы, она все равно это не сможет реализовать это со 100% надежностью.
Это забота базы данных. Забота программы — выбрать подходящую стратегию блокирования (optimistic, pessimistic, etc)

Т.е. в идеале эту ситуацию должна ловить база, а в программе просто будет валиться ошибка в случае если текущий пользователь пытается перезаписать данные другого пользователя.
Ситуация которую ты описал, это в чистом виде перезаписывание данных введенных другим пользователем.
Отредактировано 25.09.2023 10:04 bnk . Предыдущая версия . Еще …
Отредактировано 25.09.2023 10:02 bnk . Предыдущая версия .
Отредактировано 25.09.2023 10:00 bnk . Предыдущая версия .
Re: Проверка актуальности Entity перед записью
От: Dym On Россия  
Дата: 25.09.23 09:45
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>Должна ли программа оповещать пользователя при изменении данных Сущности в БД?

Да

Z>Должна ли программа проверять актуальность редактируемых свойств Сущности непосредственно перед записью в БД новых значений этих свойств?

Да

Z>Объясните, пожалуйста.

Обычно выдается сообщение типа: "Данные, которые вы отредактировали изменены другим пользователем."

Второй вариант: блокировать на уровне субд типа "select for update", тогда пока первый не откоммитится, никто больше изменить данные не сможет.
Счастье — это Glück!
Re: Проверка актуальности Entity перед записью
От: zelenprog  
Дата: 27.09.23 12:09
Оценка:
Z>>Как должна делать программа в таких случаях?
·>Разрешать конфликт — как зависит от бизнес-требований. В простейшем случае отменять изменения пользователя и просить сделать ещё раз.

Z>>Должна ли программа проверять актуальность редактируемых свойств Сущности непосредственно перед записью в БД новых значений этих свойств?

·>Да, притом с ACID.

Z>>Должна ли программа проверять актуальность редактируемых свойств Сущности непосредственно перед записью в БД новых значений этих свойств?

DO>Да
DO>Обычно выдается сообщение типа: "Данные, которые вы отредактировали изменены другим пользователем."

Суть понял.

Поясните, пожалуйста, чуть подробнее как надо сделать в следующей ситуации.

1) Читаем из базы данных таблицу товаров.
Эта таблица (назовем ее "исходная") хранится в оперативной памяти (в качестве хеша) для более комфортной работы пользователя.
2) Для отображения пользователю, все строки этой таблицы копируются в новую таблицу, но колонки копируются не все.
Некоторые поля в новой таблице форматируются. И новая таблица отображается на форме пользователю. Это "пользовательская" таблица.
Соответствие между "исходной" и "пользовательской" таблицами один-к-одному по специальному ключу.
3) Пользователь просматривает свою таблицу товаров и корректирует в ней значения.
При корректировке для валидации используется "оригинальная" таблица, так как она содержит полную информацию по товару:
— программа находит строку "исходной" таблицы, соответствующую текущей строке "пользовательской" таблицы
— проверять корректность и допустимость изменений
4) Пользователь нажимает "Записать изменения".

Что должна сделать программа перед записью для проверки актуальности отредактированных сведений?

Правильно ли я понял, что программа должна сделать следующее:
1) по каждой отредактированной строке программа читает свежие данные из базы
2) сравнивает свежие данные с данными в строке "оригинальной" таблицы
3) если данные отличаются — выдается ошибка, процесс прерывается
4) если данные совпадают — записываем указанные пользователем сведения
5) строку "оригинальной" таблицы заполняем новыми сведениями, которые были только что записаны

Верно?
Отредактировано 27.09.2023 12:13 zelenprog . Предыдущая версия . Еще …
Отредактировано 27.09.2023 12:11 zelenprog . Предыдущая версия .
Re[2]: Проверка актуальности Entity перед записью
От: Dym On Россия  
Дата: 27.09.23 12:23
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>Что должна сделать программа перед записью для проверки актуальности отредактированных сведений?

Z>Правильно ли я понял, что программа должна сделать следующее:
Z>1) по каждой отредактированной строке программа читает свежие данные из базы
Z>2) сравнивает свежие данные с данными в строке "оригинальной" таблицы
Z>3) если данные отличаются — выдается ошибка, процесс прерывается
Z>4) если данные совпадают — записываем указанные пользователем сведения
Z>5) строку "оригинальной" таблицы заполняем новыми сведениями, которые были только что записаны
Z>Верно?

Есть три версии записи:
1. В БД, назовем ее ACTUAL
2. Запрошенная пользователем, назовем ее OLD
3. Измененная пользователем, назовем ее NEW

Сравнивать нужно ACTUAL с OLD, если они не равны, значит кто-то уже успел откоммитится первым и изменять запись (накатывать NEW на ACTUAL) нельзя, об этом нужно сообщить пользователю.
Счастье — это Glück!
Re[3]: Проверка актуальности Entity перед записью
От: zelenprog  
Дата: 27.09.23 13:38
Оценка:
DO>Есть три версии записи:
DO>1. В БД, назовем ее ACTUAL
DO>2. Запрошенная пользователем, назовем ее OLD
DO>3. Измененная пользователем, назовем ее NEW
DO>Сравнивать нужно ACTUAL с OLD, если они не равны, значит кто-то уже успел откоммитится первым и изменять запись (накатывать NEW на ACTUAL) нельзя, об этом нужно сообщить пользователю.

Это я понял.

Теперь меня интересует чуть более подробный алгоритм этих действий.

Тот алгоритм, который я описал — правильный?
Вот еще раз напишу.

Есть таблица товаров, прочитанная из БД. Есть копия этой таблицы, которая отображается пользователю на форме, которую он редактирует.
То есть имеем: "оригинальная" таблица, и "пользовательская" редактируемая таблица на форме.
Пользователь отредактировал какие-то записи и какие-то поля в таблице, нажимает "Записать".
Программа должна сделать следующие действия для каждой измененной записи таблицы:
1) прочитать свежие ACTUAL данные из базы
2) сравнить свежие данные с OLD данными в строке "оригинальной" таблицы
3) если данные отличаются — выдать ошибку, процесс прерывается
4) если данные совпадают — записать указанные пользователем сведения
5) строку "оригинальной" таблицы заполнить новыми сведениями, которые были только что записаны

Все правильно?

Обращаю внимание на пункт (5). "Оригинальную" таблицу нужно же обновить?
Верно?
Re[4]: Проверка актуальности Entity перед записью
От: Dym On Россия  
Дата: 27.09.23 13:45
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>Обращаю внимание на пункт (5). "Оригинальную" таблицу нужно же обновить?

Зачем? Если ACTUAL = OLD, просто накатываются изменения в БД, и делается запрос актуальных данных из БД.
Счастье — это Glück!
Re[5]: Проверка актуальности Entity перед записью
От: zelenprog  
Дата: 27.09.23 14:28
Оценка:
Z>>Обращаю внимание на пункт (5). "Оригинальную" таблицу нужно же обновить?

DO>Зачем?


Как зачем? Пользователь ведь дальше будет продолжать работать с программой.
А наша "оригинальная" таблица после записи содержит сведения, которые были прочитаны из базы в самом начале.
Значит, каждую запись, записанную в БД, надо обновить и в "оригинальной" таблице. Она же нам и в следующий раз будет нужна, чтобы сравнить актуальные данные с прочитанными ранее.

DO>Зачем? Если ACTUAL = OLD, просто накатываются изменения в БД, и делается запрос актуальных данных из БД.


"и делается запрос актуальных данных из БД" — а запрос каких данных? Всех?
Зачем из базы читать все данные, если например пользователь отредактировал и записал всего две записи?
Re[6]: Проверка актуальности Entity перед записью
От: samius Япония http://sams-tricks.blogspot.com
Дата: 27.09.23 15:12
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>"и делается запрос актуальных данных из БД" — а запрос каких данных? Всех?

— А потом вас там публично выпорют как бродяг и отправят в Сибирь убирать снег!
— Весь?
— Да
(Навеяло)
Re: Проверка актуальности Entity перед записью
От: gyraboo  
Дата: 27.09.23 15:16
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>Объясните, пожалуйста.


В ынтерпрайзе есть 2 классических стратегии решения данной задачи, стандартной для ынтрпрайза:
— оптимистичная блокировка
— пессимистичная блокировка

Вообще кури ынтрпрайз (например, учебник гонзалвеса "изучаем jee"), там многие типовые задачи имеют стандартные проработанные решения на уровне спецификаций, чтоб ты свои кривые велосипеды не изобретал. А фреймворки типа Spring вообще имеют спектр модулей ещё шире чем кондовый ынтрпрайз, так что Spring тоже учить надо. Для расширения сознания без веществ ещё рекомендую книгу "jpa api и hibernate"
Отредактировано 27.09.2023 15:20 gyraboo . Предыдущая версия . Еще …
Отредактировано 27.09.2023 15:17 gyraboo . Предыдущая версия .
Re: Проверка актуальности Entity перед записью
От: Разраб  
Дата: 28.09.23 04:22
Оценка:
Здравствуйте, zelenprog, Вы писали:


версионирование записей БД. специальное поле которое увеличевается на 1 при обновлении.
Если при записи у вас версия меньше,значит кто-то уже успел изменить данные.
Дальше уже по желанию. тупо перезаписать. построить диалог с пользователем.
И да, вроде как подобный механизм есть в самих СУБД Multi version concurrency. Это надо по докам смотреть.
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[2]: Проверка актуальности Entity перед записью
От: zelenprog  
Дата: 28.09.23 06:00
Оценка:
Р>версионирование записей БД. специальное поле которое увеличевается на 1 при обновлении.
Р>Если при записи у вас версия меньше,значит кто-то уже успел изменить данные.
Р>И да, вроде как подобный механизм есть в самих СУБД Multi version concurrency. Это надо по докам смотреть.

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

Как быть?
Придется перечитывать запись перед записью и в "лоб" сравнивать старые и новые значения?
Re: Проверка актуальности Entity перед записью
От: vsb Казахстан  
Дата: 28.09.23 06:19
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>Как должна делать программа в таких случаях?


Должна делать так, как аналитик или менеджер скажет. А ты, как программист, должен донести до него цену разных вариантов.

Из моего опыта (цифры условны):

В 80% случаев перезаписывать — приемлемо, т.к. пользователи обычно не работают над редактированием одного и того же.

В 10% случаев перезаписывать с сохранением истории.

В 9% случаев достаточно оптимистичной блокировки. Если при записи версия изменилась, то выдавать ошибку и пусть сам разбирается дальше.

В 1% делать какой-то коллаборативный редактор, автоматическое или полуавтоматическое разрешение конфликтов и прочую муть.
Re: Проверка актуальности Entity перед записью
От: samius Япония http://sams-tricks.blogspot.com
Дата: 28.09.23 06:19
Оценка:
Здравствуйте, zelenprog, Вы писали:

Z>Как должна делать программа в таких случаях?


Z>Должна ли программа оповещать пользователя при изменении данных Сущности в БД?

Z>Должна ли программа проверять актуальность редактируемых свойств Сущности непосредственно перед записью в БД новых значений этих свойств?

Z>Объясните, пожалуйста.

Это зависит прежде всего от того, для чего пишется программа, какие требования к ней выставляются. Легко представить программы, которые должны вести себя в таких ситуациях по-разному. И даже в по-разному в рамках одной и той же программы, например, в зависимости от типа редактируемой сущности, или от прав пользователя. То же касается и вопроса о том, нужно ли сверять всю таблицу, или отдельные записи (каждую отдельно или группами по неким признакам).
Re[3]: Проверка актуальности Entity перед записью
От: Буравчик Россия  
Дата: 28.09.23 07:21
Оценка: 9 (1)
Здравствуйте, zelenprog, Вы писали:

Z>Как быть?

Z>Придется перечитывать запись перед записью и в "лоб" сравнивать старые и новые значения?

Да, перечитывать запись придется. Но сравнение можно упростить — вычислять и сравнивать хэш от строки таблицы. Хранить хэши не нужно.

Когда клиент читает данные: вычисляем хэш от строчки в БД и передаем его клиенту.

Когда клиент записывает данные: клиент передает изменения строчки, а также передает имеющийся у него хэш.
Снова вычисляем хэш от имеющейся строчки в БД, и сравниваем с клиентским.
Если хэши совпали, то данные можно записывать. Если не совпали, значит кем-то были изменены.
Best regards, Буравчик
Re[3]: Проверка актуальности Entity перед записью
От: Разраб  
Дата: 28.09.23 07:31
Оценка:
Здравствуйте, zelenprog, Вы писали:


Р>>версионирование записей БД. специальное поле которое увеличевается на 1 при обновлении.

Р>>Если при записи у вас версия меньше,значит кто-то уже успел изменить данные.
Р>>И да, вроде как подобный механизм есть в самих СУБД Multi version concurrency. Это надо по докам смотреть.

Z>В нашей платформе похоже нету такого механизма.

Z>И изменить БД, чтобы добавить это специальное поле, я не могу.

Z>Как быть?

Z>Придется перечитывать запись перед записью и в "лоб" сравнивать старые и новые значения?
если нужно, от требовании исходим
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[7]: Проверка актуальности Entity перед записью
От: zelenprog  
Дата: 28.09.23 07:39
Оценка:
Z>>"и делается запрос актуальных данных из БД" — а запрос каких данных? Всех?
S>- А потом вас там публично выпорют как бродяг и отправят в Сибирь убирать снег!
S>- Весь?
S>- Да
S>(Навеяло)

А если серьезно?
Re[4]: Проверка актуальности Entity перед записью
От: zelenprog  
Дата: 28.09.23 07:49
Оценка:
Б>Да, перечитывать запись придется. Но сравнение можно упростить — вычислять и сравнивать хэш от строки таблицы. Хранить хэши не нужно.
Б>Когда клиент читает данные: вычисляем хэш от строчки в БД и передаем его клиенту.

Б>Когда клиент записывает данные: клиент передает изменения строчки, а также передает имеющийся у него хэш.

Б>Снова вычисляем хэш от имеющейся строчки в БД, и сравниваем с клиентским.
Б>Если хэши совпали, то данные можно записывать. Если не совпали, значит кем-то были изменены.

Понятно, спасибо!

А что надо сделать после того как в базу записаны новые данные?
В этот момент у нас есть две записи для этого товара:
— первая запись в "исходной" таблице, которая содержит старые значения реквизитов и хэш
— вторая запись в отредактированной пользователем "пользовательской" таблице на форме, значения реквизитов из этой таблицы (измененные пользователем) были записаны в базу

Ясно, что мы должны обновить запись и в "исходной" таблице.
Как это правильно сделать?

Варианта два:
1) Записать новые реквизиты из записи "пользовательской" таблицы в запись "исходной" таблицы
или
2) Перечитать из БД данные о товаре в "исходную" таблицу. А также в "пользовательскую" таблицу.
Вроде как этот вариант надежнее. Однако, он менее производительный, более трудоемкий.

Как лучше сделать?
Как это обычно делается на практике в реальных хороших программах?
Отредактировано 28.09.2023 7:51 zelenprog . Предыдущая версия . Еще …
Отредактировано 28.09.2023 7:50 zelenprog . Предыдущая версия .
Re[8]: Проверка актуальности Entity перед записью
От: Dym On Россия  
Дата: 28.09.23 07:53
Оценка: 6 (1)
Здравствуйте, zelenprog, Вы писали:

Z>А если серьезно?

Если серьезно, то ровне тем же запросом, каким вы получили данные из БД в "оригинальную" таблицу:

1) Читаем из базы данных таблицу товаров.

Вот это пункт.
Счастье — это Glück!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.