2010-10-21 84 views
4

我有一個關於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錯誤:鎖等待超時超標;嘗試重新啓動事務。

它是有道理的,因爲threadA在該行上放置一個'X'鎖,以便在線程A釋放鎖之前,線程B不能獲得'X'鎖。我的問題是:從線程B的角度來看,當MySQL向我返回錯誤1205時,我怎麼能知道哪個線程/連接阻塞了我的請求(獲取表'SeqNum的'UPDATE'特權) ? 如果threadA在獲得X鎖之後什麼都不做,並且我在線程B中運行'show processlist',我所擁有的是:具有'Sleep'狀態的多個線程(我假設有超過兩個線程連接到數據庫) ,我無法確定哪個線程阻止了我的請求?

希望我明確地解釋了這個問題。謝謝!

回答

0

您在兩個會議上交易,即有您鍵入

START TRANSACTION 

通常的行爲是你的願望,即FOR UPDATE只會阻塞,直到鎖是可用的(由於COMMITROLLBACK從第一筆交易)

+0

是的,兩個會話都在交易中。我只是在我的問題中添加了交易聲明。我的問題不是爲什麼第一屆會議阻止了第二屆會議。但是,從第二屆會議來看,如何知道哪個會話阻止了它的請求?當然,我認爲有兩場以上的會議。 – WilliamLou 2010-10-21 20:11:08

+0

我誤解了你的問題,我以爲你馬上就要超時了,對不起! – 2010-10-21 20:21:00

4

你只能輕易地告訴你是否使用更新的(InnoDB插件)版本。 information_schema中有一些表格,您可以查詢:

  • SELECT * FROM information_schema.innodb_trx;
  • SELECT * FROM information_schema.innodb_locks;

在innodb_trx表中應該有一個名爲'trx_mysql_thread_id'(或類似 - 它是MySQL 5.5中的trx_mysql_thread_id)的列。這是SHOW PROCESSLIST中的ID。 (請注意,innodb_locks是錯誤名稱,它只會被鎖定等待而不鎖定)。

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插件。