Это обновление потеряно? - PullRequest
2 голосов
/ 02 марта 2011

Я просто хочу понять значение слова "потерянное обновление", которое решается транзакцией.

Пожалуйста, посмотрите на следующие две транзакции, я использую mysql 5.5.8 и механизм хранения innodb:

create table counter (what varchar(5), id integer, count integer, primary key (id));
insert into counter values ('total', 0, 0);

      session 1 (T1)                       session 2(T2)
 -------------------------------------------------------------------------
0                               |           begin;
 -------------------------------------------------------------------------
1           begin;              |        
 -------------------------------------------------------------------------
2   select count from  counter  |
    where id = 0;               |
 -------------------------------------------------------------------------
3                               |   update counter set count = 50 
                                |   where id = 0; 
 -------------------------------------------------------------------------
4                               |   commit;
 ------------------------------------------------------------------------
5  update counter set count     |
   = 1000 where id = 0;         |
 -------------------------------------------------------------------------
6           commit;             |        
 -------------------------------------------------------------------------

Вы можете считать значения 1000 и 50 следующим образом:

  1. Значение обновления 1000 зависит от значения счетчика, т. Е. Выберите.
  2. Значение обновления 50 зависит от другого чтения (не конфликтует с session1).

Итак, это типичная зависимость чтения-записи-записи.

После session1 (T1) зафиксировать и выполнить 'снова выбрать счетчик со счетчиком, где id = 0', счет будет 1000. Мне интересно, является ли обновление потерянным или не? если не почему? Если я правильно запомнил, какого-либо последнего обновления удастся избежать на любом уровне изоляции.

Одним из возможных исправлений является использование «выберите счетчик из счетчика, где id = 0 для обновления;» на шаге 2 это эквивалентно добавлению xlock к записи, и, следовательно, T2 будет заблокирован. Так что это серийный номер: [T1, T2] .

Это (известная) ошибка Innodb? Обратите внимание, что это не эквивалентно выполнению [T2, T1] , потому что T1 будет читать 50 других 0 с этой последовательностью, и конечный результат будет другим.

Спасибо

Ответы [ 2 ]

2 голосов
/ 02 марта 2011

Да, конечно, обновление потеряно.Для внешнего мира ваша транзакция действительно «выполняется» только тогда, когда она фиксируется.Сторонней организации ваша схема соответствует:

  1. Счетчик обновлений сеанса 2 до 50 для идентификатора 0
  2. Счетчик обновлений сеанса 1 до 1000 для идентификатора 0

Для этого вам даже не нужны транзакции: транзакции не имеют значения.Они имели бы значение, если бы ваша сессия 1 сделала свой выбор ПОСЛЕ того, как сессия 2 сделала свое обновление.В этом случае, с транзакциями, Сеанс 1 будет читать значение 0, но без транзакций он будет читать значение 50.

0 голосов
/ 02 марта 2011

Это связано с уровнем изоляции INNODB по умолчанию REPEATABLE READ

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...