innodb\u table\u locks设置到底做了什么?

g6baxovj  于 2021-06-18  发布在  Mysql
关注(0)|答案(1)|浏览(449)

有人能解释一下这个设置是如何影响innodb中的锁定行为的吗(举个例子)。我用不同的配置(autocommit、innodb\u table\u锁、lock table(写,读)等)。但似乎切换此选项不会以任何方式影响锁定行为。根据docs innodb\表\锁定:
在MySQL5.6中,innodb_table_locks=0对使用锁表显式锁定的表没有影响。。。写。它确实对被锁表为读或写而锁定的表有影响。。。隐式写入(例如,通过触发器)或通过锁表写入。。。阅读。
但是,即使在执行lock tables read时,将其设置为“off”也看不到任何效果。
我试过5.6,5.7,aws极光。所有人的行为都一样。
更新:这是我在storage/innobase/handler/ha\u 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\u table\u locks=0对为写而显式锁定的表没有影响呢?依我看,没有这种支票。但也许我还是漏掉了什么。

crcmnpdw

crcmnpdw1#

好吧,我想我已经弄明白了。也许这会对某人有所帮助,因为我在其他地方找不到解释。innodb_table_locks=0不适用于锁表写入的原因是,表锁也是由mdl(metadata lock manager)传递的。但是,锁表读取的行为在版本>=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 ix锁的情况下获取表上的innodb s锁。


# connection 2

set @@autocommit=0;
lock table t1 READ;

这一个将在5.6中成功,因为innodb锁定被禁用,mdl mdl\ U shared\ U read与mdl\ U shared\ U write兼容。但在5.7及更高版本中,它也将挂起,因为他们引入了一种新的锁类型mdl\u shared\u read\u only,它与mdl\u shared\u write不兼容。


# connection 3

set @@autocommit=0;
set @@innodb_table_locks = 0;
lock table t1 READ;

来自当前mysql测试用例的评论:
旧的锁方法(innodb忽略了锁表)在锁表。。。使用write是因为修复了bug#46272“mysql 5.4.4,new mdl:unnecessable”和bug#37346“innodb没有检测到update和alter table之间的死锁”。在wl#6671“通过不对innodb表使用thr#lock.c锁来提高可伸缩性”实现之后,它不再适用于读取的锁表。锁表锁现在完全由mdl子系统处理。
所以,我想他们需要更新5.7和更高版本中的文档,更重要的是,它不再适用于锁表读取;

相关问题