В таблице , где каждая строка имеет счетчик (только целое значение), мне нужно , чтобы получить текущее значение и увеличить его в то же самое время .
По сути, я хочу сделать это:
SELECT counter FROM table WHERE id=123
UPDATE table SET counter=counter+1 WHERE id=123
Но выполнение двух запросов, очевидно, не является потокобезопасным: несколько процессов, выполняющих одну и ту же операцию (в одной строке), могут получить одно и то же значение счетчика. Мне нужно , чтобы они все быть уникальным, так что каждый процесс будет получить фактическое значение тока и увеличить его на единицу.
Я могу придумать конструкцию, в которой я устанавливаю ручную блокировку для каждой строки, но мне интересно, есть ли более простой способ сделать это?
Ответы:
Операторы обновления прекрасно работают без выбора раньше! Поскольку отдельные операторы безопасны по определению, даже два запроса UPDATE, выполняемые одновременно, приведут к увеличению строки в два раза.
Если вы действительно хотите выбрать значение для своего PHP-скрипта, сделать что-то с ним, а затем хотите обновить это точное значение счетчика, вы можете сделать следующее:
Это запускает новую транзакцию, затем выбирает строки, которые вы хотите обновить, и блокирует их исключительно. Затем вы можете безопасно обновлять их, не беспокоясь о том, что другие клиенты меняют свое содержимое или даже получают доступ к заблокированным строкам. Наконец, вам нужно зафиксировать свои изменения.
Вы должны также прочитать кое-что об уровнях изоляции . Вы, вероятно, не хотите, чтобы значение, как
READ UNCOMMITTED
уровень изоляции. Все остальное должно быть хорошо для этого варианта использования.источник
UPDATE table SET counter = counter + 1
это достаточно атомно? Вы все еще нуждаетесь в заявлениях транзакции, окружающих это?FOR UPDATE
и транзакции, то выбранное вами значение может отличаться от того, которое использовалось в запросе на обновление. Моя комбинация запросов блокирует строку, как только значение выбрано, и поэтому гарантирует, что это точное значение счетчика будет использовано в запросе на обновление.