Предотвращение одновременного доступа к строкам таблицы db

StackOverflow https://stackoverflow.com/questions/8877299

Вопрос

Иногда случается, что два администратора в нашей группе поддержки пытаются выполнить одну и ту же важную операцию со строкой таблицы db (скажем, изменяя значение в строке). Нам нужно предотвратить это. (Блокировка строк невозможна, потому что таблицы являются "myisam")

Я придумал несколько решений:

установка старого значения в форме и сравнение его с текущим при отправке

родовое слово

а затем перед обновлением:

родовое слово

но может быть следующая ситуация:

  1. пользователю необходимо изменить денежную оценку с 9 долларов на 10 долларов

  2. admin1 меняет свои деньги на 10 $

  3. пользователь разумно тратит 1 доллар, поэтому его текущие деньги снова становятся 9 долларов!

  4. admin2 без предупреждения меняет свои деньги на 10 $.

создание отметки времени (столбец updated_at) в строке

То же самое, что и в решении 1. Преимущество этого подхода в том, что он говорит больше, чем просто сравнение данных. Мы можем точно сказать, были ли данные изменены, пока мы возились с формой, или нет. недостаток - мы не можем отследить, какой именно столбец был изменен, если не объединить его с решением 1

родовое слово

а затем при обновлении:

родовое слово

создание временного файла нулевой длины с именем объекта / действия

Создание / блокировка во время обновления и проверка наличие / отметка даты перед обновлением.

Перед обновлением:

родовое слово

На данный момент я предпочитаю создание файлов, потому что:

  1. Я думаю, что создать локальный файл быстрее, чем обращаться к базе данных.

  2. Мне не нужно добавлять в таблицу еще один столбец (отметку времени)

  3. Я могу легко изменить имя файла, чтобы проверить модификацию конкретного столбца, т.е. создать файл "money_user {$ userid} _modified" после завершения mysqlupdate.

Это верно или я что-то неправильно понимаю?

Это было полезно?

Решение

Вы можете указать старое значение в предложении UPDATE операции WHERE, а затем посмотреть количество затронутых строк:

Данный

родовое слово

Выполняется поток 1

родовое слово

Выполняется поток 2

родовое слово

Помимо этого, я бы, вероятно, реализовал исключение немного раньше, назначив сначала задачи отдельным администраторам, чтобы сократить время, которое тратится впустую.

Другие советы

В вашем случае, я полагаю, блокировка - лучший подход.Вы можете использовать блокировки MySQL: GET_LOCK, RELEASE_LOCK, IS_FREE_LOCK.На мой взгляд, транзакции не гарантируют, что строка не изменится, пока другой процесс выполняет свою задачу с извлеченными данными.

Хотя ваш конкретный случай не имеет ничего общего с блокировкой в традиционном смысле.IMHO, вам нужно регистрировать свои транзакции с соответствующими учетными данными и описаниями, чтобы ваши администраторы могли их читать, а не дублировать одну и ту же модификацию баланса.Блокировка может защитить от одновременного изменения строки, но не от намеренного изменения в случае перезаписи.

Я думаю, что блокировка на уровне строк базы данных не соответствует ситуации, о которой вы говорили в первом методе.Но я не думаю, что создание файла быстрее, чем доступ к системе базы данных.Очевидно, что создание файла для базы данных сложнее, чем CRUD.

Итак, я предлагаю аналогичный подход с таблицей журналирования.

  • Каждая таблица имеет свой собственный первичный ключ (например, pid).
  • Записывайте имя таблицы и идентификатор идентификатора в таблицу журнала с отметкой времени, когда кто-то пытается изменить строку.
  • Перед выполнением запроса проверьте таблицу журнала.

Взгляните на InnoDB и транзакции.Они больше подходят для чувствительных изменений (например, баланса).

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

Позвольте мне упомянуть два возможных решения, о которых вы, возможно, уже упоминали выше.

Вы можете добавить "assign_id" с идентификатором вашей учетной записи администратора в сочетании с отметкой времени, чтобы ваше приложение показывало предупреждение, если его редактирует кто-то другой.

Еще одно возможное решение - проверить, не были ли внесены какие-либо изменения при заполнении форм.Здесь можно использовать метку времени last_edited.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top