2

我创建了一个虚拟表:

CREATE TABLE `lock_test` (
  `name` varchar(32) NOT NULL,
  PRIMARY KEY (`name`)
) ENGINE=InnoDB ;

我锁定它:

LOCK TABLE lock_test write;

然后我尝试再次锁定它(相同的查询)。第二个锁定请求显然只是挂在那里。

select * from INFORMATION_SCHEMA.INNODB_LOCKS;
select * from INFORMATION_SCHEMA.INNODB_LOCK_WAITS;

都是空的(返回零结果) - 我本来希望它们被填充。我有PROCESS权限(显示PROCESSLIST锁工作)。

我对这些桌子有完全错误的看法吗?Information Schema 插件和 InnoDB 引擎肯定已安装(通过运行 SHOW PLUGINS 进行检查;)。

谢谢

4

2 回答 2

1

有趣的是 - “问题”是我试图直接锁定表两次,这似乎没有填充该表。我将其更改为两个相互干扰的事务,它按预期工作。

于 2012-04-26T07:19:50.697 回答
0

你有autocommit = 1吗?如果是,这就是原因。有两种类型的锁,在不同的层采取,一种在 MySQL 层,一种在存储引擎 (InnoDB) 层。

来自 MySQL 文档,表锁定和事务的交互

当您调用 时LOCK TABLES,InnoDB 内部会使用自己的表锁,而 MySQL 会使用自己的表锁。InnoDB 在下一次提交时释放它的内部表锁,但是要让 MySQL 释放它的表锁,你必须调用UNLOCK TABLES. 您不应该有autocommit = 1,因为InnoDB 在调用 后立即释放其内部表锁LOCK TABLES,并且很容易发生死锁。InnoDB 根本不获取内部表锁autocommit = 1,以帮助旧应用程序避免不必要的死锁。

还要检查这部分文档(最后 2 段):InnoDB 中不同 SQL 语句设置的锁

LOCK TABLES设置表锁,但设置这些锁的是 InnoDB 层之上的更高 MySQL 层。InnoDB 知道表锁 if innodb_table_locks = 1(默认) 和autocommit = 0,并且 InnoDB 上面的 MySQL 层知道行级锁。

于 2012-04-25T00:42:27.490 回答