MYSQL: тупик с простыми запросами

У меня есть таблица «клики», в которую я добавляю записи каждый раз, когда пользователь перемещается по специальному счетчику-скрипту click.php. Эта таблица не имеет столбца автоинкремента, она имеет transaction_id CHAR(32) в качестве первичного ключа, который генерируется случайным образом перед вставкой новой записи. Каждая новая запись имеет столбец normalized=0,

Каждые 3 минуты фоновый демон запускает транзакцию, читает все новые клики WHERE normalized=0 и группирует это к столу stats, Единственный запрос записи для этой таблицы UPDATE clicks SET normalized=1 WHERE normalized=0 выполняется в конце всей обработки, а затем транзакции фиксируются.

Проблема заключается в том, что каждый раз, когда во время этой транзакции перемещается файл click.php, скрипт не может добавить новую запись в «клики» и завершается ошибкой:

SQLSTATE[40001]: Serialization failure:
1213 Deadlock found when trying to get lock; try restarting transaction

INSERT  `clicks`
SET `transaction_id`='3520359d597ba05b635ff15feb334229',
`time`='2016-04-29 15:14:31',
...,
`normalized`='0'

Я знаю, что могу решить это, используя LOCK TABLESНо я просто хочу знать, почему возникает этот тупик.

UPD:
Я вижу следующую причину в выводе SHOW ENGINE INNODB STATUS:

*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 252763 page no 124 n bits 480 index `normalized`
of table `tds`.`clicks` trx id C1329EF lock_mode X locks gap before
rec insert intention waiting

0

Решение

(это должен быть комментарий, но он длинный и сложный)

Что такое режим изоляции транзакций?

Я никогда не сталкивался с этим раньше — в основном потому, что я избегаю использования транзакций с множественными утверждениями, например,

UPDATE clicks
SET normalized=2
WHERE normalized=0;

INSERT INTO stats (transaction_id, clicks)
SELECT transaction_id, COUNT(*)
FROM clicks
WHERE normalized=2
GROUP BY transaction_id;

UPDATE clicks
SET transaction_id=1
WHERE transaction_id=2;

Есть способы сделать это с помощью одного обновления таблицы кликов, если вы используете отдельный столбец и сгенерированный идентификатор для набора данных. И если вы запускаете это из cron, вам, вероятно, следует заключить их в цикл GET_LOCK () … RELEASE_LOCK (), чтобы предотвратить параллелизм. Хотя модель поддерживает параллелизм для большинства моделей транзакций, она немного ухудшает производительность, когда дела уже идут плохо.

0

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector