Могут ли мои операторы UPDATE работать, если они выполняются одновременно в MySQL? - PullRequest
0 голосов
/ 20 ноября 2018

Я видел много похожих вопросов, но все же я не до конца уверен, что я прав.

У нас есть приложение, которое запускает задание для массовой отправки множества сообщений.Статус доставки сообщений будет получен позже в пакетном режиме и в произвольном порядке.

Структура таблицы выглядит следующим образом: -

CREATE TABLE `message` (
  `pk` char(32) NOT NULL DEFAULT '',
  `job_id` varchar(40) DEFAULT NULL,
  `status` varchar(40) DEFAULT NULL,
  `update_date` datetime DEFAULT NULL,
  PRIMARY KEY (`pk`),
  KEY `job_id` (`job_id`),
  KEY `status` (`status`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Записи изначально создаются с status, установленным на ноль.Ожидается, что его значение изменится с нуля на sent, а затем на delivered.Приведенные ниже операторы используются для обновления записей.

Когда устанавливается статус - delivered

Update message SET status = 'delivered', update_date = Now()
    WHERE job_id = :someId

Когда устанавливается статус - sent

Update message SET status = 'sent', update_date = Now()
    WHERE job_id = :someId AND status IS NULL

Проблема в том, что возможно, что два потока одновременно пытаются установить status одной и той же записи на «отправлено» и «доставлено».В этом случае «поставлено» является окончательным статусом, поэтому мы бы хотели, чтобы он в конечном итоге победил.

Гарантируют ли приведенные выше утверждения это в MySql или MariaDB?

Ответы [ 3 ]

0 голосов
/ 20 ноября 2018
Update message SET status = 'sent', update_date = Now()
WHERE job_id = :someId
AND status != 'delivered';
0 голосов
/ 21 ноября 2018

Да, в MySQL и MariaDB (и, вероятно, в любой базе данных SQL).обновления в той же строке являются атомарными.

  • «отправлено» перезапишет NULL, но не «доставлено»
  • «доставлено» перезапишет NULL и «отправлено»

Это то, что вы хотите.Просто убедитесь, что сообщение с заданным идентификатором job_id существует, прежде чем обновлять его:)

0 голосов
/ 20 ноября 2018
Update message SET status = 'delivered', update_date = Now()
    WHERE job_id = :someId
      AND status = 'sent'    -- add this??

(В этой области не должно быть различий между MySQL и MariaDB.)

...