LINUX.ORG.RU

У меня блокировки в MySQL не сходятся с тем что в справочной документации.

 


0

1

Изучаю MySQL, так что в нем я нуб.

В документации к MySQL 5.7 (5.7.12) написано следующее:

14.2.2.7 Locks Set by Different SQL Statements in InnoDB
...
LOCK TABLES sets table locks, but it is the higher MySQL layer above the InnoDB layer that sets these locks. InnoDB is aware of table locks if innodb_table_locks = 1 (the default) and autocommit = 0, and the MySQL layer above InnoDB knows about row-level locks.
Otherwise, InnoDB's automatic deadlock detection cannot detect deadlocks where such table locks are involved. Also, because in this case the higher MySQL layer does not know about row-level locks, it is possible to get a table lock on a table where another session currently has row-level locks.

Из выше сказанного, как я понял, следует что если innodb_table_locks = 1 и autocommit = 0 то только тогда блокировки InnoDB уровня строки и блокировки установленные оператором LOCK TABLES видят друг друга, и иначе не видят и лезут друг на друга.

Но в действительности у меня в (MySQL 5.7.10) выходит не так, все способы блокировки «учитывают» друг друга. Так при autocommit=1 с таблицей блокированно оператором LOCK TABLES сессия все равно замирает при попытке SELECT ... FOR UPDATE, и на оборот. Кроме того такое же точно поведение наблюдается даже при innodb_table_locks = 0.

Например:

Сессия1:
> LOCK TABLES tabtest READ;
Сессия2:
> START TRANSACTION;
> SELECT * FROM tabtest FOR UPDATE;
ждет...
или:
Сессия1:
> LOCK TABLES tabtest WRITE;
Сессия2:
> START TRANSACTION;
> SELECT * FROM tabtest LOCK IN SHARE MODE;
ждет...
или:
Сессия1:
> START TRANSACTION;
> SELECT * FROM tabtest LOCK IN SHARE MODE;
Сессия2:
> LOCK TABLES tabtest WRITE;
ждет...

Почему такое несоответствие написанному в доках, или я чего-то неправильно понял?

★★★

Давай условно считать, что в мускуле есть только table-level lock, не зря же ровные пацаны горячий бекап репликацией делают. Сбережешь себе кучу нервов, в отличии от меня.

cnupm
()

А что, собственно, не так?

Например:

Первая сессия заблокировала таблицу на чтение, вторая сессия, которая хочет получить исключительную блокировку на запись, будет ждать, пока первая снимет блокировку

или:

Здесь с точностью до наоборот: первая сессия получила исключительную блокировку, все остальные будут ждать.

или:

То же, что и (1)

sjinks ★★★
()
Последнее исправление: sjinks (всего исправлений: 1)
Ответ на: комментарий от sjinks

А что, собственно, не так?

Так написно же:

... InnoDB is aware of table locks if innodb_table_locks = 1 (the default) and autocommit = 0 ...
Otherwise ... the higher MySQL layer does not know about row-level locks, it is possible to get a table lock on a table where another session currently has row-level locks.

По моему четко описны условия при которых InnoDB видит блокировки таблиц (а при каких нет). А иначе не должен видеть. Меня смущает что на моем компьютере InnoDB видит эти блокировки и при несоблюдении оговоренных условий.

normann ★★★
() автор топика
Ответ на: комментарий от normann

Попробуй в SELECT WHERE добавить… Без условия у тебя блокируется вся таблица, поэтому вероятно, что ставится table level lock вместо row level.

И еще учти, что In MySQL 5.7, innodb_table_locks=0 has no effect for tables locked explicitly with LOCK TABLES ... WRITE.

Вообще как я это понимаю, с innodb_table_locks=0 LOCK TABLES может успешно выполниться, потому что именно LOCK TABLES зависит от innodb_table_locks.

Это следует из

LOCK TABLES acquires two locks on each table if innodb_table_locks=1 (the default). In addition to a table lock on the MySQL layer, it also acquires an InnoDB table lock. Versions of MySQL before 4.1.2 did not acquire InnoDB table locks; the old behavior can be selected by setting innodb_table_locks=0. If no InnoDB table lock is acquired, LOCK TABLES completes even if some records of the tables are being locked by other transactions.

Т.е. такой сценарий может сработать:

# Session 1
SELECT * FROM table FOR UPDATE;

# Session 2
LOCK TABLES table READ;
sjinks ★★★
()
Ответ на: комментарий от sjinks

Собственно, у тебя то же самое написано:

it is possible to get a table lock on a table where another session currently has row-level locks.

А ты тестируешь сценарий, где у тебя уже есть table lock, а ты пытаешься получить row-level lock.

sjinks ★★★
()
Ответ на: комментарий от sjinks

Попробуй в SELECT WHERE добавить…

Все равно, ничего не поменялось, ожидает.

normann ★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.