Является ли «обновить токены установленными токенами = токены + 1» в InnoDB? - PullRequest
11 голосов
/ 07 декабря 2011

Без использования явных транзакций, это:

update tokens set tokens = tokens + 1

гарантированно будет атомарным в InnoDB?

Ответы [ 2 ]

1 голос
/ 07 декабря 2011

Насколько я понимаю, в режиме автоматической фиксации (т. Е. "Без явных транзакций") один оператор - это одна транзакция.Поскольку транзакция по определению атомарна, то и ваш отдельный оператор также атомарен.

Однако, когда дело доходит до оценки ограничений, это делается не на уровне оператора (то есть транзакции), а построчно, показаявление обработано.

Если у вас есть уникальное ограничение (индекс) для столбца tokens, это обновление скорее всего завершится неудачей из-за этого.То же самое верно для внешних ключей, ссылающихся на ту же таблицу.

0 голосов
/ 07 декабря 2011

Я думаю, что нет.Мои уровни изоляции / шпаргалки MySQL недоступны, но я думаю, что они будут атомарными на уровне строк (UPDATE будет использовать блокировку диапазона IIRC), но не на уровне таблиц.

Теперь более интересный вопрос, чем то, является ли UPDATE атомарным, когда неатомарность UPDATE равна наблюдаемой .Ответ заключается в том, что отдельные операторы на уровне изоляции READ UNCOMMITTED могут наблюдать неатомарность UPDATE, а ряд связанных операторов в одной транзакции на уровне изоляции READ COMMITTED может наблюдать различные обновления.REPEATABLE READ и SERIALIZABLE видят ОБНОВЛЕНИЯ, как если бы они были атомарными и согласованными.

Представьте себе два сеанса.Сеанс A имеет уровень изоляции SERIALIZABLE и выполняет: UPDATE tokens SET tokens = tokens + 1 в таблице с 1000 строками.

  • Предположим, что сеанс B имеет уровень изоляции READ UNCOMMITTED и выполняет SELECT sum(tokens) FROM tokens → Этот выбор может видеть частичное обновление (то есть: некоторые строки обновлены, а другие строки не обновлены).
  • Предположим, что сеанс B имеет уровень изоляции READ COMMITTED и выполняет SELECT sum(tokens) FROM tokens → Этот выбор не может видеть частичное обновление, поэтому он видит UPDATE, как если бы он был атомарным.
  • Предположим, что сеанс B имеет уровень изоляции READ COMMITTED и выполняет SELECT sum(tokens) FROM tokens WHERE id BETWEEN 1 AND 100; SELECT sum(tokens) FROM tokens WHERE id BETWEEN 501 AND 600, а затем некоторая логика программы добавляет эти два значения → Эти SELECT могут видеть разные снимки MVCC → разные обновления,
  • Предположим, сеанс Bимеет уровень изоляции REPEATABLE READ и выполняет SELECT sum(tokens) FROM tokens WHERE id BETWEEN 1 AND 100; SELECT sum(tokens) FROM tokens WHERE id BETWEEN 501 AND 600, а затем некоторая программная логика добавляет эти два значения → Эти SELECT не могут видеть разные снимки MVCC → они видят одно и то же обновление,
...