У меня вопрос о SQL и стратегии блокировки. Например, предположим, что у меня есть счетчик просмотров изображений на моем веб-сайте. Если у меня есть sproc или аналогичный для выполнения следующих утверждений:
START TRANSACTION;
UPDATE images SET counter=counter+1 WHERE image_id=some_parameter;
COMMIT;
Предположим, что счетчик для конкретного image_id имеет значение "0" в момент времени t0. Если две сессии, обновляющие один и тот же счетчик изображений, s1 и s2, начинаются одновременно с t0, есть ли вероятность того, что эти два сеанса прочитают значение "0", увеличьте его до "1" , и оба попытаются обновить счетчик до "1" ', поэтому счетчик получит значение' 1 'вместо' 2 '?
s1: begin
s1: begin
s1: read counter for image_id=15, get 0, store in temp1
s2: read counter for image_id=15, get 0, store in temp2
s1: write counter for image_id=15 to (temp1+1), which is 1
s2: write counter for image_id=15 to (temp2+1), which is also 1
s1: commit, ok
s2: commit, ok
Конечный результат: неверное значение '1' для image_id = 15, должно быть 2.
Мои вопросы:
- Возможна ли эта сценария?
- Если да, имеет ли уровень изоляции транзакции?
- Существует ли конфликтный конфликт, который бы обнаружил такой конфликт как ошибку?
- Можно ли использовать какой-либо специальный синтаксис, чтобы избежать проблемы (что-то вроде Compare and Swap (CAS) или явных методов блокировки)?
Мне интересен общий ответ, но если его нет, меня интересуют ответы на вопросы, связанные с MySql и InnoDB, так как я пытаюсь использовать этот метод для реализации последовательностей в InnoDB.
EDIT: Также возможен следующий сценарий, приводящий к такому же поведению. Я предполагаю, что мы находимся на изолированном уровне READ_COMMITED или выше, так что s2 получает значение с начала транзакции, хотя s1 уже написал "1" счетчику.
s1: begin
s1: begin
s1: read counter for image_id=15, get 0, store in temp1
s1: write counter for image_id=15 to (temp1+1), which is 1
s2: read counter for image_id=15, get 0 (since another tx), store in temp2
s2: write counter for image_id=15 to (temp2+1), which is also 1
s1: commit, ok
s2: commit, ok