Избегайте поврежденных данных для запроса SELECT и UPDATE, а также между долгосрочными задачами - PullRequest
1 голос
/ 23 сентября 2019

У меня есть два приложения exporter и payment_handler

  • exporter выполняет SELECT * FROM orders WHERE status="PAID", обрабатывает строки (около 5 минут) и, наконец, UPDATE orders SET status="EXPORTED" WHERE status="PAID"
  • payment_handler выполняет UPDATE orders SET status="PAID" WHERE status="UNPAID"

Без изоляции транзакции это приведет к неправильному обновлению данных при выполнении payment_handler, когда exporter обрабатывает строки: оператор UPDATEэкспортера помечает заказы как экспортированные, которые оператор SELECT не выбирал ранее.

Если я оберну экспортер в транзакции и сделаю SELECT с квалификатором FOR UPDATE, payment handler будетзаблокирован до exporter, потому что MySQL не разрешает новые вставки status="PAID".Но обработчик платежей не должен быть заблокирован на такой длительный срок.

Мой текущий обходной путь - избежать транзакции и создать собственный «снимок» данных: exporter создает временную таблицу export_ids иделает вставку, как это: INSERT INTO export_ids SELECT id FROM order WHERE status="PAID".Все последующие операции SELECT и UPDATE для таблицы order в exporter присоединят / отберут таблицу export_id.С точки зрения производительности и хранилища это работает нормально, поскольку в export_ids будет только около 100 тыс. Записей для одного экспорта.

Но мне интересно, правильно ли я использую уровни транзакций MySQLs и есть лиЕсть ли лучший способ достичь поведения?

1 Ответ

1 голос
/ 24 сентября 2019

Только не делайте этого:

UPDATE orders SET status="EXPORTED" WHERE status="PAID"

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

UPDATE orders SET status="EXPORTED" WHERE id IN (<list of previously selected ids>)

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

Примечание: я не говорю, что вам не нужны блокировки.Вы, вероятно, делаете.Но не для этих двух задач.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...