I saw many similar questions but still I am not fully sure if I am correct.
We have an application which launches a job to mass send many messages. The messages delivery status are received later in batches and in no particular order.
The table structure is like:-
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;
The records are initially created with status
set to null. Its value is expected to change from null to sent
and then to delivered
. Below statements are used to update the records.
When status to be set is - delivered
Update message SET status = 'delivered', update_date = Now()
WHERE job_id = :someId
When status to be set is - sent
Update message SET status = 'sent', update_date = Now()
WHERE job_id = :someId AND status IS NULL
Problem is, that it is possible that there could be two threads concurrently trying to set the status
of same record to 'sent' and 'delivered'. In this case 'delivered' is the final status so we would want that to win eventually.
Will the above statements ensure this in MySql or MariaDB?
Yes, in both MySQL and MariaDB (and probably any SQL database). updates to the same row are atomic.
This is what you want. Just make sure message with given job_id exists before updating it :)