MySQL InnoDB锁问题
我有一个关于 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连接,我将它们命名为线程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错误:Lock wait timeout超过;尝试重新启动事务。
这是有道理的,因为线程 A 在该行上放置了“X”锁,因此线程 B 无法获得“X”锁,直到线程 A 释放该锁。
现在,我的问题是:从线程B的角度来看,当MySQL向我返回错误1205时,我如何知道哪个线程/连接阻止了我的请求(以获得表'SeqNum'的'UPDATE'权限)? 如果线程A在获得X锁后什么也不做,并且我在线程B中运行“显示进程列表”,那么我所拥有的只是:几个具有“睡眠”状态的线程(我假设有两个以上的线程连接到数据库),我无法识别哪个线程阻止了我的请求?
希望我清楚地解释了这个问题。谢谢!
I have a question about MySQL InnoDB. For example: I have the following table created:
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)
Now, I have two mysql connections to the same database, I name them as Thread A and B.
In thread A, I have the following SQL statement:
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)
and then, I just leave the thread A as it is.
In thread B, I would like to do the same query:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql>SELECT `current_seq_num` FROM SeqNum WHERE `id` = 'current' FOR UPDATE;
thread B will throw an MySQL 1205 Error after the lock waiting time out: Lock wait timeout exceeded; try restarting transaction.
It makes sense, because threadA put a 'X' lock on that row, so that thread B can NOT get the 'X' lock until thread A release the lock.
Now, my question is: from the perspective of thread B, how could I know which thread/connection block my request (to obtain the 'UPDATE' privilege for the table 'SeqNum') when MySQL return Error 1205 to me?
If threadA is doing nothing after it obtains the X lock, and I run 'show processlist' in thread B, all I have are: several threads with 'Sleep' Status (I assume there are more than two threads connected to the datbase), I can NOT identify which thread blocked my request?
Hopefully, I explained the question clearly. Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
InnoDB 插件将为您提供锁定和锁定查询的清晰图片。
例如
会给你一个锁定和阻塞交易。只是你必须安装 innodb 插件。
InnoDB plugin will give you a clear picture of the locked and the locking queries.
For instance
will give you a locking and blocking transactions. Only you have to have innodb plugin installed.
您只能轻松判断您是否使用较新的(InnoDB 插件)版本。 information_schema 中有一些表可以查询:
在 innodb_trx 表中应该有一个名为“trx_mysql_thread_id”的列(或类似的列 - 在 MySQL 5.5 中是 trx_mysql_thread_id)。这是 SHOW PROCESSLIST 中的 id。
(请注意,innodb_locks 的命名错误。它只会填充锁等待,而不填充锁)。
You can only easily tell if you use a newer (InnoDB Plugin) release. There are some tables in information_schema which you can query:
In the innodb_trx table there should be a column called 'trx_mysql_thread_id' (or similar - it is trx_mysql_thread_id in MySQL 5.5). That is the id in SHOW PROCESSLIST.
(Note that innodb_locks is misnamed. It will only be populated for lock-waits, not locks).
我认为在这个阶段,查询“SHOW ENGINE INNODB STATUS\G”可以解决我的问题。
以下是 MySQL 手册中的信息:
http://dev.mysql.com /doc/refman/5.0/en/innodb-monitors.html#innodb-standard-monitor
在线程 B 中运行此查询,您将在“事务”部分获得阻止您的请求的线程
I think at this stage, the query "SHOW ENGINE INNODB STATUS\G" could solve my problem.
Here is the info from MySQL manual:
http://dev.mysql.com/doc/refman/5.0/en/innodb-monitors.html#innodb-standard-monitor
run this query in thread B, you will get the thread which blocked your request in "transaction" section
您是否在两个会话上都处于事务中,即您是否键入了
通常的行为将如您所愿,即
FOR UPDATE
只会阻塞,直到锁可用(由于COMMIT
code> 或来自第一个事务的ROLLBACK
)Are you in a transaction on both sessions, i.e. have you typed
Normally the behaviour would be as you desire, i.e. a
FOR UPDATE
would just block until the lock were available (due toCOMMIT
orROLLBACK
from the first transaction)