MYSQL - Являются ли вставки с включенной автоматической фиксацией считающимися одношаговым или многошаговым процессом? - PullRequest
0 голосов
/ 22 января 2020

В MYSQL, если условная вставка выполняется с включенным автокоммитом, ie.

set autocommit true;
insert into blah (x,y,z) values (1,2,3) where not exists (.....);

Будет ли приведенный выше оператор выполняться атомарно и фиксироваться одновременно? Или возможно, что может быть задержка между выполнением вставки и выполнением фиксации?

РЕДАКТИРОВАТЬ: Обновлен оператор вставки, чтобы отразить более точный запрос:

set autocommit true;
insert into foo (x,y,z) select 1,2,3 from dual where not exists (select 1 from bar where a = 1);

Я хочу вставить, только если строка в другой таблице не существует . Я хочу подтвердить, что в приведенном ниже сценарии произойдет сбой:

SESSION1: вставить в foo ..... там, где его нет (выберите 1 из бара, где a = 1);

СЕССИЯ2: вставить в столбец (a) значения (1);

СЕССИЯ2: зафиксировать;

СЕССИЯ1: зафиксировать; // здесь не получится.

1 Ответ

2 голосов
/ 22 января 2020

Это работает так же, как и при отсутствии автоматической фиксации, но вы начинаете новую транзакцию, немедленно делаете INSERT, а затем немедленно COMMIT без задержки.

START TRANSACTION;
INSERT ...
COMMIT;

Это атом c, в том смысле, что никакой другой клиент не увидит вашу ВСТАВКУ в частично завершенном состоянии. Атомность не в скорости, а в том, чтобы убедиться, что изменение либо совершено полностью, либо нет вообще. В других сеансах нет полусоставленного состояния.


Кстати, синтаксис, который вы показываете, INSERT INTO ... VALUES ... WHERE NOT EXISTS ... не имеет смысла. INSERT не имеет предложения WHERE. Возможно, вы думаете о INSERT, который использует строки, выводимые оператором SELECT:

INSERT INTO ...
SELECT ... FROM ... WHERE ...;

Если вы сделаете это, вы НЕ будете использовать предложение VALUES() для вашего INSERT.


Учитывая ваш обновленный вопрос, он не может работать так, как вы показываете.

SESSION1: вставить в foo ....., где не существует (выберите 1 в строке, где a = 1);

Если вы используете уровень изоляции транзакции по умолчанию REPEATABLE-READ, это приведет к блокировке пробела в bar, где будет существовать строка, в которой будет a=1. Это делается для того, чтобы гарантировать отсутствие изменений в последних зафиксированных записях в таблице, которую читал запрос.

SESSION2: вставить в bar (a) значения (1);

Это заставляет сеанс ждать, потому что он не может заблокировать разрыв для вставки. Время ожидания истечет с ошибкой, если сеанс 1 не будет зафиксирован в течение innodb_lock_wait_timeout секунд (по умолчанию 50).

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