Блокировки уровня строки MySQL

Я не уверен в том, как работает блокировка на уровне строк, но вот моя проблема. У меня есть таблица T (id int, balance int) (engine = InnoDB), которую я хочу заблокировать для строк, имеющих ID = 1, поэтому я начинаю транзакцию, например это :

start transaction ; 
select * from T where ID = 1 FOR UPDATE ; 

Перед отправкой фиксации я хотел попробовать, действительно ли строки ЗАБЛОКИРОВАНЫ. Итак, я начал другой сеанс и набрал:

UPDATE T set balance = balance  + 100 where ID = 1 ;

Здесь я ясно вижу, что жду блокировку (тайм-аут через 30 сек).

Но когда я набираю:

UPDATE T set balance = balance  + 8500 where ID = 2 ;

Я тоже жду блокировки, так как я могу просто заблокировать строки с ID = 1, а не таблицу целиком?


person Lilo    schedule 23.09.2016    source источник
comment
Есть ли индекс в столбце ID?   -  person Barmar    schedule 23.09.2016
comment
Нет, это важно????   -  person Lilo    schedule 23.09.2016
comment
Да. Он блокирует все строки, которые ему пришлось прочитать для выполнения запроса. Если столбец не проиндексирован, он должен прочитать все строки в таблице, чтобы найти те, где ID = 1, и блокирует их каждую по мере чтения. Когда столбец проиндексирован, ему не нужно сканировать таблицу (блокировка фактически реализована в индексе).   -  person Barmar    schedule 23.09.2016


Ответы (1)


Вам нужно добавить индекс в столбец id, чтобы гарантировать, что вы получите блокировку на уровне строки. SELECT ... FOR UPDATE блокирует все строки, которые считываются для выполнения запроса, а не только строки, которые фактически выбраны. Без индекса он должен выполнить полное сканирование таблицы, поэтому в результате блокируется каждая строка.

С индексом он просто блокирует эту запись индекса, ему не нужно читать какие-либо другие строки, поэтому никакие другие строки не будут заблокированы.

person Barmar    schedule 23.09.2016