Что именно делает установка innodb_table_locks? - PullRequest
0 голосов
/ 13 октября 2018

Может кто-нибудь объяснить, как этот параметр влияет на поведение блокировки в innodb (с примером).Я провел многочисленные эксперименты с различными конфигурациями (autocommit, innodb_table_locks, LOCK TABLE ... (WRITE, READ) и т. Д.) Из разных потоков.Но похоже, что переключение этой опции никак не влияет на поведение блокировки.Согласно документам innodb_table_locks :

В MySQL 5.6 innodb_table_locks = 0 не действует для таблиц, заблокированных явно с помощью LOCK TABLES ... WRITE.Это имеет эффект для таблиц, заблокированных для чтения или записи с помощью LOCK TABLES ... WRITE неявно (например, с помощью триггеров) или LOCK TABLES ... READ.

Но я неувидеть любой эффект, установив его в положение «ВЫКЛ», даже когда выполняю LOCK TABLES READ.

Я пробовал на 5.6, 5.7, AWS Aurora.Все ведут себя одинаково.

ОБНОВЛЕНИЕ : Это то, что я нашел в исходном коде хранилища / innobase / handler / ha_innodb.cc:

 if (thd_sql_command(thd) == SQLCOM_LOCK_TABLES
            && THDVAR(thd, table_locks)
            && thd_test_options(thd, OPTION_NOT_AUTOCOMMIT)
            && thd_in_lock_tables(thd)) {

            dberr_t error = row_lock_table_for_mysql(
                prebuilt, NULL, 0);

            if (error != DB_SUCCESS) {
                DBUG_RETURN(
                    convert_error_code_to_mysql(
                        error, 0, thd));
            }
        }

Итак, почемуони говорят в документах, что установка innodb_table_locks = 0 не имеет никакого эффекта для таблиц, заблокированных явно для записи?Из того, что я вижу, нет такой проверки.Но, вероятно, я все еще что-то упускаю.

1 Ответ

0 голосов
/ 17 октября 2018

Хорошо, я думаю, что-то понял.Может быть, это будет полезно для кого-то, так как я не нашел объяснения в другом месте.Причина, по которой innodb_table_locks = 0 не работает для LOCK TABLE WRITE , заключается в том, что блокировки таблиц также передаются MDL (диспетчером блокировки метаданных).Однако поведение для LOCK TABLE READ отличается в версиях> = 5.7, и я думаю, что документы устарели.

Вот пример:

#connection 1
drop table if exists t1; 
create table t1 (id integer primary key, x integer) engine=INNODB;
insert into t1 values(0, 0),(1,1),(2,2);
begin;
SELECT * FROM t1 WHERE x = 0 FOR UPDATE;

Этот зависнет, так как он пытается получить блокировку innodb S на столе, в то время как первое соединение удерживает innodb IX блокировка.

#connection 2 
set @@autocommit=0;
lock table t1 READ;

Эта попытка будет успешной в 5.6, так как блокировка innodb отключена и MDL MDL_SHARED_READ совместим с MDL_SHARED_WRITE .Однако в 5.7 и выше он также будет зависать, потому что они ввели новый тип блокировки MDL_SHARED_READ_ONLY , который не совместим с MDL_SHARED_WRITE .

#connection 3 
set @@autocommit=0;
set @@innodb_table_locks = 0;
lock table t1 READ; 

Комментарий оттекущие тестовые случаи MYSQL:

Старый метод блокировки (где LOCK TABLE был проигнорирован InnoDB) больше не работает, когда используется LOCK TABLE ... WRITE из-за исправления ошибок # 46272 "MySQL 5.4.4, новый MDL: ненужный и ошибка # 37346 «innodb не обнаруживает тупик между обновлением и изменением таблицы». После того, как WL № 6671 «Улучшить масштабируемость за счет отсутствия использования блокировок thr_lock.c для таблиц InnoDB», он больше не работает для LOCK TABLES READтакже. LOCK TABLES блокировки теперь полностью обрабатываются подсистемой MDL.

Итак, я думаю, что им нужно обновить документы в 5.7 и более поздних версиях, чтобы упомянуть, что они больше не работают даже для LOCK TABLE READ ;

...