1つのスレッドに対して1つのテーブル行を明示的に選択する方法を探しています。私は約50の並列プロセスで動作するクローラーを作成しました。すべてのプロセスは、テーブルから1行を取り出して処理する必要があります。高並列接続のテーブル行を1つだけ選択してください
CREATE TABLE `crawler_queue` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`url` text NOT NULL,
`class_id` tinyint(3) unsigned NOT NULL,
`server_id` tinyint(3) unsigned NOT NULL,
`proc_id` mediumint(8) unsigned NOT NULL,
`prio` tinyint(3) unsigned NOT NULL,
`inserted` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `proc_id` (`proc_id`),
KEY `app_id` (`app_id`),
KEY `crawler` (`class_id`,`prio`,`proc_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
は今、私のプロセスは、次の手順を実行します。
は- スタートDBトランザクション
- が
SELECT * FROM crawler_queue WHERE class_id=2 AND prio=20 AND proc_id=0 ORDER BY id LIMIT 1 FOR UPDATE
- のような選択を行うトランザクションコミット
UPDATE crawler_queue SET server_id=1,proc_id=1376 WHERE id=23892
- で、この行を更新
これは、他のプロセスがまだ処理されている行を取得できないようにするために役立ちます。やって選択番組
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE crawler_queue ref proc_id,crawler proc_id 3 const 617609 Using where
にEXPLAINしかし、時には、私は私のログにエラー/警告(5分毎程度)の2種類見ることができるので、プロセスは、高すぎる並列処理を引き起こすように見える:
mysqli::query(): (HY000/1205): Lock wait timeout exceeded; try restarting transaction (in /var/www/db.php l
ine 81)
mysqli::query(): (40001/1213): Deadlock found when trying to get lock; try restarting transaction (in /var/www/db.php line 81)
を
私の質問です:これらのロックの問題を最小限に抑えるために誰かが正しい方向に向けることができますか?
EDIT 2012年12月29日(生産状態で、並列性が今よりも3-4倍高くなるであろう、私はずっとロックの問題があるだろうという想定):私は、インデックスcrawler
を使用するようにSELECT
を修正しましたヒントでUSE INDEX(crawler)
。私の問題は、lockwaitのタイムアウトがもうなくなりました(デッドロックが消えました)。
EDIT 2012年12月31日:USE INDEX()
とEXPLAIN
は(。表は今より多くのデータが含まれているため、無行のは、高いです)今示しています
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE crawler_queue ref proc_id,crawler crawler 5 const,const,const 5472426 Using where
'LAST_INSERT_ID()'は、 'INSERT'データまたは' UPDATE'が自動インクリメント列をインクリメントする場合にのみ値を返します:** EDIT ** http://stackoverflow.com/questions/ 1388025 /最後に更新された行内のmysqlの試行 – rabudde
何らかの理由で、テストしたときにlast_insert_idの値を取得しましたが、それは私を騙しました(正しいもののように見えますが、それはそうではなかった)。私はそのSOの質問に記載されている解決策は行く方法だと思います。私は私の答えも更新します。 – Xnoise