Оператор InnoDB SELECT… FOR UPDATE блокирует все строки в таблице

Версия сервера MySQL 5.1.41 с включенным подключаемым модулем InnoDB. У меня есть следующие три таблицы для счетов-фактур: invoice, invoice_components и invoice_expenses. Таблица invoice имеет первичный ключ invoice_id. И invoice_components, и invoice_expenses связаны с таблицами invoice с invoice_id в качестве неуникального foreign_key (каждый счет-фактура может иметь более одного компонента и более одного расхода). Обе таблицы имеют индекс BTREE для этого внешнего ключа.

У меня есть следующие транзакции:

транзакция 1

START TRANSACTION; 
SELECT * FROM invoices WHERE invoice_id = 18 FOR UPDATE; 
SELECT * FROM invoice_components WHERE invoice = 18 FOR UPDATE; 
SELECT * FROM invoice_expenses WHERE invoice = 18 FOR UPDATE; 

Все работает нормально для первой транзакции, и строки выбираются и блокируются.

транзакция 2

START TRANSACTION; 
SELECT * FROM invoices WHERE invoice_id = 19 FOR UPDATE; 
SELECT * FROM invoice_components WHERE invoice = 19 FOR UPDATE; 
SELECT * FROM invoice_expenses WHERE invoice = 19 FOR UPDATE; 

Вторая транзакция возвращает ОШИБКА 1205 (HY000): Превышено время ожидания блокировки; попробуйте перезапустить транзакцию для третьего запроса.

То же самое происходит, когда я пытаюсь ВЫБРАТЬ ... ДЛЯ ОБНОВЛЕНИЯ другие счета, их компоненты и расходы. Кажется, первая транзакция заблокировала все строки в таблице invoice_expenses. Есть идеи, почему это происходит?

Дополнительная информация

Транзакция 2 начинается после третьего запроса транзакции 1. На сервере нет других пользователей, подключений или транзакций.

Проблема возникает в ПОВТОРИЕМОМ ЧТЕНИИ по умолчанию. уровень изоляции транзакции. Исправляется переходом на уровень READ COMMITTED. Это решение, но оно все еще не объясняет, почему проблема возникает с invoice_expenses, а не с invoice_components.

9
задан Maxim Krizhanovsky 15 July 2011 в 14:21
поделиться