Один такой оператор работает так же с MyISAM или InnoDB, с транзакцией или с autocommit = ON. Он блокирует достаточно для выполнения запроса, тем самым блокируя другое соединение. Когда закончено, другое соединение продолжается. Во всех случаях столбец скоро уменьшается на 11.
Третий пользователь может увидеть значение, уменьшенное на 0, 4, 7 или 11. «Очень точное время» на самом деле невозможно, потому что в какой-то момент выполнения каждого оператора проверяется / устанавливается / любой однопотоковый блокиратор , То есть они будут сериализованы, настолько быстро, что вы не сможете их увидеть.
InnoDB блокирует только строки, а не таблицы. (ОК, оператор DDL делает более смелые блокировки.)
Что становится более интересным, так это транзакция, которая изменяет две вещи или занимает заметное количество времени:
Преднамеренный случай: один предмет, но требуется время:
BEGIN;
SELECT something;
think about it for a while
UPDATE that something;
COMMIT;
Выбор должен быть написан так:
SELECT something FOR UPDATE;
Это говорит другим соединениям: «Я собираюсь обновить строку; пожалуйста, не путайте меня». (Я привожу этот пример, потому что многие новички упускают эту тонкость.)
Случай тупика: возиться с 2 вещами:
BEGIN; -- in one connection
UPDATE thing_1;
UPDATE thing_2;
COMMIT;
BEGIN; -- in another connection, at the "exact same time"
UPDATE thing_2;
UPDATE thing_1;
COMMIT;
Это классический пример тупика - каждый хватает одно, а потом тянется к другому. Очевидно, что это не может быть сделано для работы. Одна транзакция уничтожена; другой завершает. Следовательно, вы должны проверить на наличие ошибок, чтобы вы могли обнаружить это.
Обычной реакцией на тупик является воспроизведение всей неудачной транзакции. К тому времени другое соединение не будет мешать, и оно должно продолжаться без проблем. (ОК, еще одно соединение может создать еще один тупик.)
Задержка: если два соединения захватывают несколько вещей в одном и том же порядке, то одно может быть отложено до завершения другого. Чтобы не допустить «ожидания вечно», по умолчанию существует 50 секунд innodb_lock_wait_timeout
. Ваша пара простых UPDATEs
на самом деле пример этого случая. Один закончится быстро; другой останавливается, пока не закончится первый.
Обратите внимание, как Deadlock можно (в некоторых случаях) превратить в Задержку, последовательно упорядочив вещи, к которым вы прикасаетесь.
autocommit = 1: с этим параметром и без вызова BEGIN
каждый оператор эффективно:
BEGIN;
your statement
COMMIT;
autocommit = 0: это проблема с ожиданием Когда вы выполняете запрос записи, BEGIN
неявно генерируется. Тем не менее, это ваша ответственность в конечном итоге выпустить COMMIT
. Если вам это не удастся, вы удивитесь, почему ваша система зависла. (Еще одна распространенная ошибка новичка.) Мой совет: «Никогда не используйте =0
».