まえがき
これは、とあるウェブプログラマーがやらかした事件の手記である。
返事がない
ある日、Railsでmigrationを書いて、デプロイしたときに、ブラウザ氏からこう言われた。
502 Bad Gateway
nginx/1.4.3
_人人人人人人_
> 突然の死 <
 ̄Y^Y^Y^Y^Y ̄
まったくシャレにならないので、なんとかしよう。
原因を究明しよう
まず、原因を探ろう。
よくよく思い出してみると、マイグレーションが重すぎて途中停止してるっぽかった。その頃からアクセスが死んだようにも思える。
ということは、何かの拍子にDBをロックしてしまった可能性が高い。
ロック、聴くぶんには大好きだけどハメられるとすごく辛い。しかも死んでるし。
で、mysqlのprocesslist
を確認する。原因となる作業プロセスがいるはずだ。
processlistの探り方
基本はUNIXのpsとかとだいたい同じ。アレのSQL版。
> show processlist;
| 284788 | tbaba | localhost:33573 | forkwell_dev | Sleep | 1 | | NULL |
| 285029 | tbaba | localhost:37715 | forkwell_dev | Query | 3595 | Waiting for table metadata lock | SELECT DISTINCT `job_endorsements`.`id` AS t0_r0, `job_endorsements`.`job_id` AS t0_r1, `job_endors |
| 285342 | tbaba | localhost:43623 | forkwell_dev | Query | 3654 | Waiting for table metadata lock | ALTER TABLE `users` DROP `facebook_identifier` |
| 285347 | tbaba | localhost:43685 | forkwell_dev | Query | 3599 | Waiting for table metadata lock | SELECT `users`.* FROM `users` WHERE `users`.`id` IN (9987, 5353, 8381, 9298, 8885, 9979, 519, 5805, |
| 285350 | tbaba | localhost:43717 | forkwell_dev | Query | 3566 | Waiting for table metadata lock | SELECT `users`.* FROM `users` WHERE `users`.`id` = 298 LIMIT 1 |
| 285351 | tbaba | localhost:43725 | forkwell_dev | Query | 3555 | Waiting for table metadata lock | SELECT `users`.* FROM `users` WHERE `users`.`id` = 9920 LIMIT 1 |
| 285352 | tbaba | localhost:43726 | forkwell_dev | Query | 3558 | Waiting for table metadata lock | SELECT `users`.* FROM `users` WHERE `users`.`id` = 298 LIMIT 1 |
| 285353 | tbaba | localhost:43729 | forkwell_dev | Query | 3555 | Waiting for table metadata lock | SELECT `users`.* FROM `users` WHERE `users`.`id` = 298 LIMIT 1 |
| 285354 | tbaba | localhost:43731 | forkwell_dev | Query | 3553 | Waiting for table metadata lock | SELECT `users`.* FROM `users` WHERE `users`.`id` = 9545 LIMIT 1 |
| 285355 | tbaba | localhost:43736 | forkwell_dev | Query | 3544 | Waiting for table metadata lock | SELECT DISTINCT `job_endorsements`.`id` AS t0_r0, `job_endorsements`.`job_id` AS t0_r1, `job_endors |
2行目を見て欲しい。"Waiting for table metadata lock"と書いてある。
metadata lobkについてはここを見てもらうことにして、とにかくこいつらをどうにか動くようにしたい。
さっきUNIXのpsとだいたい同じ、と書いたが、まぁ消すときもだいたい同じだ。
> kill 284788
Query OK, 0 rows affected (0.00 sec)
で、消える。
こいつが原因だったらしく、こいつを消したらその他のロック解除待ちプロセスは一斉に解決されて、待ちプロセスはゼロになった。
あとがき
一番良いのはmetadata lockを引き起こさないようなコードを書くことだと思うので、ちゃんとトランザクションとかを意識して書けば良いと思う。
あと、ALTER TABLEには気をつけよう。