Чи слід блокувати рядки в моїй хмарній БД під час їх редагування користувачем


12

Я створюю настільний додаток, який зберігає дані у хмарі. У мене є одна проблема - почати редагувати елемент у програмі та залишати його на деякий час, викликаючи застарілі дані. Це, очевидно, також може статися, якщо 2 людини намагаються одночасно редагувати той самий елемент. Коли вони закінчують редагування і хочуть зберегти дані, мені потрібно або перезаписати те, що зараз існує в базі даних, або перевірити, чи почали вони редагувати після останньої зміни, або змусити їх відмовитись від змін або, можливо, дати їм можливість ризикувати перезапис чужих змін.

Я думав над тим, щоб додати поля is_lockedта lock_timestampдо таблиці БД. Коли користувач починає редагувати елемент, рядок буде змінено is_lockedна true та встановить часову позначку блокування на поточний час. Тоді у мене буде деякий час, протягом якого тримається замок (наприклад, 5 хвилин). Якщо хтось інший спробує відредагувати елемент, він отримає повідомлення про те, що елемент заблоковано, а коли блокування автоматично закінчується. Якщо користувач вимкнеться під час редагування блокування, автоматично закінчується через відносно короткий проміжок часу, і як тільки це стане, користувач буде попереджений, що термін дії блокування закінчився, і він буде змушений перезапустити редагування після оновлення даних.

Це був би хороший метод запобігання перезапису застарілих даних? Це надмірність (я не очікую, що програму використовуватимуть більше кількох людей одночасно на одному акаунті).

(У мене є ще одна проблема - 2 людини, які отримують замок на той самий предмет, однак я вважаю, що це стан гонки, з яким мені комфортно.)


1
"Ще одна проблема, яку я маю - це 2 люди, які отримують замок на той самий предмет, однак я вважаю, що це комфортний стан для мене", - використання транзакції з базою даних навколо придбання блокування повинно запобігати таким умовам змагань.
Жуль

Більшість двигунів баз даних (як мінімум, реляційних типів) мають підтримку цього. Це дуже поширена концепція у світі RDBMS, і навіть "іграшкові" бази даних обробляють її досить добре, враховуючи, що ви говорите їй, що хочете оптимістичного або песимістичного блокування. У будь-якому випадку, я не думаю, що це щось, що потрібно будувати самостійно: перевірити параметри вашого двигуна db, щоб побачити, як з ним працювати.
jleach

Той факт, що ваша програма - це настільний додаток ( товстий клієнт ), не має великого значення. Він може бути сконструйований так само, як і високодоступне багатокористувацьке серверне додаток.
Хосам Алі

Відповіді:


19

Одне, що вам тут допоможе, - це термінологія. Те, що ви тут описуєте, називається "песимістичним блокуванням". Основна альтернатива такому підходу - «оптимістичне блокування». Під час песимістичного блокування кожен актор повинен заблокувати запис перед оновленням та випустити блокування після завершення оновлення. Оптимістично блокуючи, ви припускаєте, що ніхто інший не оновлює запис і спробуйте. Оновлення не вдається, якщо запис було змінено іншим актором.

Оптимістичне блокування, як правило, є кращим, якщо шанс двох акторів оновити одну і ту ж річ одночасно низький. Песимістичний зазвичай використовується, коли шанс високий або вам потрібно знати, що ваше оновлення зможе досягти успіху перед початком. На мій досвід, оптимістичне блокування майже завжди є кращим, оскільки існує багато проблем, властивих песимістичному блокуванню. Одне з найбільших питань стосується вашого запитання. Користувачі можуть заблокувати запис для редагування, а потім залишити обід. Ваші пом’якшення допоможуть у цьому, але досвід користувачів не буде кращим за оптимістичний підхід і, ймовірно, буде набагато гіршим. Наприклад, один користувач відкриває запис, починає його оновлювати, і їх начальник з'являється за своїм столом. Інший користувач намагається редагувати запис. Це заблоковано. Другий користувач продовжує пробувати і через 5 хвилин, термін дії блокування закінчується, а другий користувач оновлює запис. Перший користувач повертається на екран, намагається зберегти, і йому кажуть, що він втратив замок. Тепер у тому ж сценарії з усім тим самим, за винятком оптимістичного блокування, досвід першого користувача майже такий же, але другий користувач не чекає 5 хвилин.

Схему, яку ви виклали, було б значно вдосконалено, застосувавши оптимістичне блокування для значення блокування, але я вважаю, що оптимістичне блокування, ймовірно, добре для всієї справи, і ви можете позбутися поля is_locked.

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

Ось основний рецепт: замість поля is_locked поле має номер номера версії. Коли ви отримуєте запис, витягуєте поточну версію запису. Під час оновлення ви робите контингент оновлення в полі версії, що відповідає тому, що ви отримали, і збільшує його на успіх. Якщо версія не відповідає, оновлення не має ефекту, і ви повідомляєте про це як про помилку.


Це дуже корисна відповідь. Чи можете ви пояснити, чому песимістичне блокування перешкоджає, коли є невеликий шанс "зіткнення". Це виключно тому, що потрібно навіть зайти в базу даних, щоб навіть почати редагування, або через додаткову складність чи іншу причину? Дякую!
yitzih

3
@yitzih Деякі пропонували прочитати: Fowler et al, Patterns of Enterprise Application Architecture . У цьому питанні є ціла глава, з хорошим обговоренням усіх варіантів та причин їх вибору.
Жуль

2
@Jimmy - Ваша відповідь чудова. У деяких випадках повідомлення про помилку назад не є достатнім. Розглянемо випадок, коли користувач витрачає кілька хвилин на оновлення запису. У такому випадку, лише невдача може виявитися недостатньо хорошою, можливо, ви хочете дати користувачеві можливість об'єднати зміни, що відбулися, з тими, які здійснив інший користувач. Я б сказав, що оптимістичне блокування може потребувати вирішення конфлікту залежно від ваших вимог.
Джон Рейнор

3
Варто зазначити, що песимістичне блокування набагато простіше пояснити клієнту. Якщо ви пишете повідомлення про те, що клієнт не може отримати доступ до запису, тому що його зараз редагує інший, клієнт розуміє просто чудово і, як правило, приймає його. Якщо ви замість цього скажете клієнтові після збереження, що збереження було неможливим, оскільки його вже оновлено іншим користувачем 7/10, клієнт буде розчарований та / або очікувати пояснень щодо цієї дивної поведінки програми.
Ніл

2
@Neil Це правда, і я думаю, що часто песимістичне блокування використовується, коли оптимістичніше підходить. Часто робочий процес робить дуже малоймовірним виникнення зіткнення.
JimmyJames

0

З відповіді @ JimmyJames ми можемо побачити, як саме питання стосується досвіду користувачів .

Все залежить від контексту. Скільки часу та сил потрібно на оновлення запису? Як часто кілька користувачів хочуть оновити один і той же документ?

Наприклад, якщо вашим користувачам зазвичай потрібно кілька секунд, щоб оновити запис, і це мало суперечок, то оптимістичне блокування - це, мабуть, шлях. У гіршому випадку користувачеві доведеться витратити ще кілька секунд, можливо, і хвилину, щоб оновити документ.

Якщо ваш документ дуже спірний, але добре структурований, можливо, ви можете дозволити їм фіксувати окремі поля з кроком 30 секунд, показуючи таймер або ненав'язливе повідомлення, щоб дозволити їм розширити замок.

Однак якщо ваші користувачі витрачають значну кількість часу чи зусиль, то слід розглянути інші підходи. Ваша запис добре структурована? Чи можете ви показати користувачам порівняння (відмінність) між версією на сервері та версією, яку вони намагаються зберегти? Чи можете ви виділити відмінності? Чи можете ви дозволити їм об'єднати зміни? Подумайте про досвід, який ви хочете мати зі своїми інструментами контролю джерела. Ви дійсно не хочете, щоб вас змушували писати весь цей код ще раз!

Ви можете подивитися на Документи Google для додаткового натхнення. Можливо, ви можете показати користувачам сповіщення про збереження нової версії. Можливо, ви можете показати їм, скільки людей мають запис відкритим, щоб вони могли вибратись повернутися в менш спірний час.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.