Если Вы уже нормализуете исходные данные к булевским переменным, то! = xor.
bool(a) != bool(b)
При выполнении операций DML
, InnoDB
блокирует все отсканированные строки, не сопоставленные.
Рассмотрим этот макет таблицы:
DROP TABLE t_tran;
CREATE TABLE t_tran (id INT NOT NULL PRIMARY KEY, data INT NOT NULL, KEY ix_tran_data (data)) Engine=InnoDB;
DROP TABLE t_tran;
CREATE TABLE t_tran (id INT NOT NULL PRIMARY KEY, data INT NOT NULL, KEY ix_tran_data (data)) Engine=InnoDB;
INSERT
INTO t_tran
VALUES
(1, 1),
(2, 2),
(3, 3),
(4, 4),
(5, 5),
(6, 6),
(7, 7),
(8, 8);
START TRANSACTION;
DELETE
FROM t_tran
WHERE data = 2
AND id <= 5;
В данном случае MySQL
] выбирает путь доступа RANGE
для id
, что он считает более дешевым, чем REF
для данных
.
В параллельной транзакции вы сможет удалять или обновлять строки 6
, 7
, 8
, но не строки 1
до 5
, поскольку они заблокированы (несмотря на то, что была затронута только строка 2
).
Если вы удалите id <= 5
из условия выше, вы сможете удалить любую строку но строка 3
.
К сожалению,вы не можете контролировать пути доступа MySQL
в операциях DML
.
Лучшее, что вы можете сделать, - это правильно проиндексировать ваши условия и надеяться, что MySQL
выберет эти индексы.
Убедитесь, что ваша изоляция транзакции помечена как зафиксированная при чтении и не повторяющееся чтение. Чтение зафиксировано должно быть по умолчанию, но мы видели, что на нашем сервере по умолчанию innodb было повторным чтением.
Вы можете проверить, выполнив следующее:
SHOW VARIABLES LIKE 'tx%';
Чтобы установить это, в вашем файле my.cnf введите следующую строку:
tx_isolation=READ-COMMITTED