WWW::Mechanize の履歴数
社内のサポート用途で WWW::Mechanize を使ったスクリプトを作っていたのだけれど、扱うデータが増えるとメモリリークが起きるのでどうしたもんかと思ってた。
そうこうしているうちに、クライアントさんの仕事の方が忙しくなってきたので、しばらく放置してたら半年近く経ってしまってた。。
そろそろ解決しないとと重い腰をあげて、原因を調べていったらどうやら WWW::Mechanize のアクセス履歴に上限が付いてないのが問題の様子。
マニュアルをちゃんと読むと、「履歴数には上限がなくてデフォルトのまま使うと無限です」ということらしい。
それはメモリリークも起きるわ。
調べていたら、履歴数を制限できなくてインスタンス作り直すとかback()使ってなんとかがんばるとか、苦労の跡が滲んだ情報があったのだけど、最近のバージョンには stack_depth というのがあって、それに上限数を設定できるようになったみたい。
my $mech = WWW::Mechanize->new( stack_depth => 1);
とするとメモリリーク起きなくなったー。
めでたしめでたしかと思いきや。。
WWW::Mechanize でアクセスしている Web サーバが搭載されているデバイスが原因不明のハングアップを繰り返すところにはまってる。
これでまた半年放置というのはいただけないので何とかせななー。
スパムとハム
スパムの語源はモンティパイソンのコントからだから食べ物の名前というのは知ってたけれど、スパムじゃないメールはそれに対してハムって言うんですね。スパムじゃないからハム。
知らなかった。
Wikipedia にも乗ってるそうで。
ハムとかスパムとかおなか減ってきた。
RewriteLog と RewriteLogLevel を使ってリダイレクトのデバッグをする
自分用にメモなのでわからん!!という人ゴメン。
Apache の mod_rewrite を使ってリダイレクトの設定をしてみるが期待どおり動かない。
そんな時は RewriteLog と RewriteLogLevel ディレクティブを設定してデバッグを試みる。
この2つは .htaccess には書けない。 httpd.conf とかの方で。
ErrorLog の設定とかと同じかな。
RewriteLog /your/web/site/logs/rewrite_log RewriteLogLevel 3
とか。
RewriteLog はログファイル名の指定。
RewriteLogLevel 3 は出力レベルの指定。 0 だと出力なし。マニュアルのサンプルに 3 て書いてあったからここでも 3。
要 Apache 再起動。
integer 型カラムを serial 型に変更する
先日、integer 型で設計していたカラムを serial 型に変えたくなりました。
変えたいというよりは変えないといけなくなりました、が正しいのかも。
運営期間が長くなるとそういうこともあるもんですね。
数年前の自分たちの設計はなんて古いんだと思いますが、当時は知らなかった手法や使えなかった技術があるんだから仕方がないのだ、と自分に言い聞かせてます。
単に自分がバカだったからとは考えないようにしています。。
integer 型だったカラムを serial 型に変えるには、カラムの型変更の正攻法 では上手くできません。
実際やってみても DB に serial という型は存在しないと言われます。
ALTER TABLE your_table ALTER COLUMN this_col TYPE serial; ERROR: type "serial" does not exist
serial というのは型の種類として扱われていない、ということなんでしょうか。
たしかに psql コマンドラインで見てみると、serial 型は
your_db=> \d your_table Table "public.your_table" Column | Type | Modifiers ------------+-----------------------+----------------------------------- this_col | integer | not null default nextval('your_table_this_col_seq'::regclass) that_col | text |
という定義がされています。
Type は integer となっていて、 Modifiers との合わせ技で serial というフォーマットを実現している様です。
ということは、運用中の integer 型カラムの Modifiers のところに上記と同じ条件がつけられれば serial 型として振舞えるのではないか、と推測しました。
ここから読み取れる Modifiers の条件は次の3つ。
1. not null
2. default nextval() がセットされている
3. sequence がある
変更前の状況はというと。
DB は PostgreSQL 8.2.3 で、カラムはこんな感じ。
your_db=> \d your_table Table "public.your_table" Column | Type | Modifiers ------------+-----------------------+----------------------------------- this_col | integer | not null that_col | text |
幸い not null はすでに設定されていたので、 sequence を作ってやって、その sequence に this_col の最大値をセットしてやり、this_col のデフォルト値には出来上がった sequience の nextval を使うようにしてやる、と。
CREATE SEQUENCE your_table_this_col_seq; SELECT SETVAL('your_table_this_col_seq', (SELECT MAX(this_col) FROM your_table)); ALTER TABLE your_table ALTER this_col SET DEFAULT nextval(your_table_this_col_seq'::regclass);
これで期待通り this_col を省略して INSERT INTO としても自動的に 1 インクリメントされた this_col が設定されるようになりました。
ちなみに ::regclass というのはオブジェクト識別子データ型とかいうものらしく、nextval の引数にはそういう型にキャストして渡さないといけないということの様です。
よく分かってませんが、そのまま書いてみたら動いたしまあいいか。