有人可以解释此设置如何影响innodb中的锁定行为(示例)。我用不同的线程(自动提交,innodb_table_locks,LOCK TABLE ...(写,读)等)进行了许多实验。但是似乎切换此选项不会以任何方式影响锁定行为。根据文档innodb_table_locks:
在MySQL 5.6中,innodb_table_locks = 0对用LOCK TABLES ... WRITE显式锁定的表无效。对于通过LOCK TABLES ... WRITE隐式(例如,通过触发器)或LOCK TABLES ... READ锁定的表进行读取或写入,确实有作用。
但是,即使执行LOCK TABLES READ,即使将其设置为“ OFF”,我也看不到任何效果。
我尝试使用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对显式锁定的表无效呢?从我看来,没有这种检查。但是可能我仍然缺少一些东西。
答案 0 :(得分:0)
好的,我想我已经解决了。也许这对某人会有所帮助,因为我在其他任何地方都找不到解释。 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 IX 锁的同时将innodb S 锁定在表上。
#connection 2
set @@autocommit=0;
lock table t1 READ;
由于禁用了innodb锁定,并且MDL MDL_SHARED_READ 与 MDL_SHARED_WRITE 兼容,因此该版本将在5.6中成功。但是,在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) 当使用LOCK TABLE ... WRITE修复错误时可以工作#46272 “ MySQL 5.4.4,新的MDL:不必要和错误#37346” innodb不会 检测更新和变更表之间的死锁。” WL#6671之后 “通过不对InnoDB表使用thr_lock.c锁来提高可伸缩性” 已实现,它也不再适用于LOCK TABLES READ。锁 TABLES锁现在完全由MDL子系统处理。
因此,我想他们需要在5.7及更高版本中更新文档,以提及即使 LOCK TABLE READ ;