Поток для блокировки, который у меня есть в настоящее время, равен SELECT ... FOR UPDATE
, за которым следует INSERT
. например,
BEGIN;
SELECT count(*) FROM test WHERE col = 1 FOR UPDATE;
# check to ensure an invariant will still be met after the insert.
INSERT INTO test (col) VALUES (1);
COMMIT;
Я ожидал, что SELECT
выше получит эксклюзивную блокировку чего-либо, чтобы предотвратить одновременное нахождение нескольких вызывающих абонентов в критическом разделе, но похоже, что по умолчанию InnoDB получает только общую блокировку для таблицы или пробела индекса , Если две одновременные транзакции пытаются сделать это одновременно, они оба могут получить общую блокировку, но одна из них завершится с ошибкой взаимоблокировки при попытке вставить.
Есть ли способ заставить этот код вести себя как стандартная пессимистическая блокировка для предотвращения одновременного чтения?
Примечание: я знаю, что в некоторых случаях уникальный индекс может решить эту проблему, но я сталкивался с двумя случаями, когда уникальный индекс недостаточен (1), когда один из столбцов обнуляем, и я хочу ровно одно нулевое значение и (2) когда я хочу гарантировать другой инвариант о строках, как будто должно быть меньше 10 строк с данным ключом.