MySQL транзакции: множественные параллельные транзакции и целостность данных - PullRequest
4 голосов
/ 22 сентября 2010

Я использую транзакции для управления данными из нескольких таблиц MySQL InnoDB в достаточно сложном веб-приложении.Вкратце, данная транзакция работает следующим образом:

  1. Данные считываются из строки в таблице «user_point_totals»
  2. Различные махинации вычисляют, какой должна быть общая сумма новой точки пользователя
  3. Новая записьсоздается в таблице «user_point_totals», отражающей обновленную итоговую сумму

Допустим, пользователь A выполняет какое-то действие, имеющее разветвления, связанные с точками, выполняется шаг 1, этот поток выполнения считывает общее количество очков пользователя в память,и приложение начинает вычислять новый итог.Тем временем пользователь B выполняет действие, которое влияет на общее количество баллов пользователя A, и начинается другая транзакция;однако первая транзакция еще не завершена, поэтому второй поток получает ту же общую сумму баллов, что и начальная точка, как первая транзакция (из той же строки таблицы).Впоследствии транзакция 1 завершает и создает новую сумму очков пользователя с ее восприятием того, каким должно быть новое значение, и вскоре после этого транзакция 2 завершает и создает новую строку также для суммы очков пользователя.Тем не менее, общее количество очков второй транзакции теперь неверно, так как в нем не учитывается новый итог, созданный транзакцией 1.

Мои вопросы:

  • Этот сценарий невозможен из-заатомарную природу транзакций, которую я, по-видимому, понимаю не так хорошо, как следовало бы?
  • Если нет, то как обеспечить целостность данных в подобных ситуациях?

Спасибо за внимание!

1 Ответ

3 голосов
/ 22 сентября 2010

На техническом уровне вы можете использовать возможности блокировки таблиц (или блокировки строк) MySQL. Это позволит вам определить, действительно ли кто-то вычисляет что-то, используя таблицу. С другой стороны, этот метод потребует многих соображений, например, что произойдет в случае сбоя процесса и т. Д.

Однако на практическом уровне я сомневаюсь, что вы захотите сделать что-то подобное. Такие операторы, как sum () или avg () в MySQL, уже оптимизированы для этой цели. Если вам нужно получить сумму по некоторым столбцам таблицы и получить ответ в таблице, вы можете использовать представление или создать временную таблицу (возможно, но медленнее). У вас не должно быть столбца, который содержит значение, которое можно вычислить из других столбцов. Эта ситуация приводит к несоответствиям, поскольку неясно, какое поле является истинным, если отношение не сбалансировано. (Это ошибка входного скрипта или преднамеренное повторное использование поля каким-то программистом?)

Во-вторых, обязательно используйте таблицы InnoDB в вашем экземпляре MySQL, иначе ваша система не будет полностью ACID-совместимой, то есть вы не получите требуемый атомарный характер.

...