Я использую SELECT ... FOR UPDATE, чтобы применить уникальный ключ.Моя таблица выглядит так:
CREATE TABLE tblProductKeys (
pkKey varchar(100) DEFAULT NULL,
fkVendor varchar(50) DEFAULT NULL,
productType varchar(100) DEFAULT NULL,
productKey bigint(20) DEFAULT NULL,
UNIQUE KEY pkKey (pkKey,fkVendor,productType,productKey)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Таким образом, строки могут выглядеть следующим образом:
{'Ace-Hammer','Ace','Hammer',121},
{'Ace-Hammer','Ace','Hammer',122},
...
{'Menards-Hammer','Menards','Hammer',121},
...
Итак, обратите внимание, что «Ace-Hammer» и «Menards-Hammer» могут иметь один и тот же productKey, толькокомбинация «продукт + ключ» должна быть уникальной.Требование, что это целое число, определенное таким образом, является организационным, я не думаю, что это то, что я могу сделать с auto_increment, используя innoDb, но, следовательно, вопрос.
Так что, если поставщик создает новую версиюсуществующий продукт, мы даем ему отдельный ключ для этой комбинации поставщика / продукта (я понимаю, что столбец pkKey в этих примерах является избыточным).
Моя хранимая процедура имеет вид:
CREATE PROCEDURE getNewKey(IN vkey varchar(50),vvendor varchar(50),vkeyType varchar(50)) BEGIN
start transaction;
set @newKey=(select max(productKey) from tblProductKeys where pkKey=vkey and fkVendor=vvendor and productType=vkeyType FOR UPDATE);
set @newKey=coalesce(@newKey,0);
set @newKey=@newKey+1;
insert into tblProductKeys values (vkey,vclient,vkeyType,@newKey);
commit;
select @newKey as keyMax;
END
Это все!В периоды интенсивного использования (тысячи пользователей) я вижу: Дублирующую запись «Ace-Hammer-Ace-Hammer-44613» для ключа «pkKey».
Я могу повторить транзакцию, но это не такошибка, которую я ожидал, и я хотел бы понять, почему это происходит.Я мог понять блокировку строк, вызывающую взаимоблокировку, но в этом случае кажется, что строки вообще не заблокированы.Интересно, проблема в max () в этом контексте или, возможно, в табличном индексе.Эта операция является единственной транзакцией, которая выполняется на этой таблице.
Любое понимание приветствуется.Я прочитал несколько постов MySql / SO на эту тему, большинство проблем и проблем, похоже, связано с оверлоком или тупиками.Например, здесь: Что именно блокирует FOR UPDATE в MySQL, что именно блокируется?