【问题标题】:What does innodb_table_locks setting do exactly?innodb_table_locks 设置究竟做了什么?
【发布时间】:2018-10-13 11:34:55
【问题描述】:

谁能解释一下这个设置如何影响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。所有行为都相同。

更新: 这是我在 storage/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 对显式锁定以进行写入的表没有影响?据我所知,没有这样的检查。但可能我仍然缺少一些东西。

【问题讨论】:

    标签: mysql innodb locks


    【解决方案1】:

    好的,我想我有点想通了。也许这对某人有帮助,因为我在其他任何地方都没有找到解释。 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_READMDL_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 测试用例的评论:

    旧的锁定方法(InnoDB 忽略了 LOCK TABLE)不再 由于修复了错误 #46272 而在使用 LOCK TABLE ... WRITE 时工作 “MySQL 5.4.4,新 MDL:不必要和错误 #37346”innodb 没有 检测更新和更改表之间的死锁”。在 WL#6671 之后 “通过不对 InnoDB 表使用 thr_lock.c 锁来提高可伸缩性” 已实现它不再适用于 LOCK TABLES READ 。锁 TABLES 锁现在完全由 MDL 子系统处理。

    所以,我猜他们需要在 5.7 及更高版本中更新文档,以提及它不再适用于 LOCK TABLE READ

    【讨论】:

    • 请向 bugs.mysql.com 提交一个“文档”错误
    猜你喜欢
    • 2012-07-23
    • 2016-09-10
    • 2023-03-15
    • 2012-10-17
    • 2021-06-04
    • 1970-01-01
    • 2018-07-30
    • 2019-10-06
    • 2021-01-01
    相关资源
    最近更新 更多