我对MySQL InnoDB有疑问。例如:我创建了以下表格:
mysql>CREATE TABLE IF NOT EXISTS `SeqNum`
(
`id` varchar(10) NOT NULL,
`seq_num` BIGINT(30) default 0,
PRIMARY KEY(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.00 sec)
mysql>INSERT IGNORE INTO `SeqNum` VALUES('current',0);
Query OK, 1 rows affected (0.00 sec)
现在,我有两个到同一个数据库的mysql连接,我将它们命名为Thread A和B. 在线程A中,我有以下SQL语句:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select `seq_num` from SeqNum where `id`='current' FOR UPDATE;
+---------+
| seq_num |
+---------+
| 0 |
+---------+
1 row in set (0.01 sec)
然后,我只是将线程A保留原样。
在主题B中,我想做同样的查询:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql>SELECT `current_seq_num` FROM SeqNum WHERE `id` = 'current' FOR UPDATE;
线程B将在锁定等待超时后抛出MySQL 1205错误:超过锁定等待超时;尝试重新启动交易。
这是有道理的,因为threadA在该行上放置了一个'X'锁,因此线程B无法获得'X'锁定,直到线程A释放锁定。
现在,我的问题是:从线程B的角度来看,当MySQL向我返回错误1205时,我怎么能知道哪个线程/连接阻塞了我的请求(获取表'SeqNum'的'UPDATE'特权)? 如果threadA在获得X锁之后什么都不做,并且我在线程B中运行'show processlist',那么我只有:几个具有'Sleep'状态的线程(我假设有两个以上的线程连接到数据库),我无法确定哪个线程阻止了我的请求?
希望我能清楚地解释这个问题。谢谢!
答案 0 :(得分:7)
InnoDB插件将为您提供锁定和锁定查询的清晰图片。
例如
SELECT r.trx_id waiting_trx_id, r.trx_mysql_thread_id waiting_thread,
r.trx_query waiting_query,
b.trx_id blocking_trx_id, b.trx_mysql_thread_id blocking_thread,
b.trx_query blocking_query
FROM information_schema.innodb_lock_waits w
INNER JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id
INNER JOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id;
会给你一个锁定和阻止交易。只有你必须安装innodb插件。
答案 1 :(得分:4)
您只能轻松判断是否使用了较新的(InnoDB Plugin)版本。 information_schema中有一些表可以查询:
在innodb_trx表中应该有一个名为'trx_mysql_thread_id'的列(或类似的 - 它在MySQL 5.5中是trx_mysql_thread_id)。这是SHOW PROCESSLIST中的id。
(请注意,innodb_locks名称错误。只会填充锁定等待而不是锁定。)
答案 2 :(得分:2)
我认为在这个阶段,查询“SHOW ENGINE INNODB STATUS \ G”可以解决我的问题。 以下是MySQL手册中的信息: http://dev.mysql.com/doc/refman/5.0/en/innodb-monitors.html#innodb-standard-monitor
在主题B中运行此查询,您将获得在“交易”部分
中阻止您的请求的主题答案 3 :(得分:0)
您是否参与了两个会话的交易,即您输入了
START TRANSACTION
通常行为会按照您的意愿行事,即FOR UPDATE
只会在锁定可用之前阻止(由于第一笔交易中的COMMIT
或ROLLBACK
)