スポンサーサイト

一定期間更新がないため広告を表示しています


- | | - | - | ↑TOP | BlogRanking
PostgreSQLテクニカルセミナー
PostgreSQLテクニカルセミナー&第7回会員総会というセミナーに参加してまいりました。
参加費は無料なのでふるってご参加しました。
DBというとMYSQLしか使った事ないんだけど、Postgresも興味があり使ってみたかったんで行ってみました。

場所は恵比寿ガーデンプレイスです。
ガーデンプレイスってこれで行くのは二回目なんですけどきれいな建物ですよねー。
ちなみに一回目はレベルXというファミコン20周年記念イベントで訪れました。

会場に着くと結構参加者がいてびっくりです(失礼な)。
まあ、大体ほぼ95%位男性ですな。
で、記念品?にこんなの貰いました。

水

水ですよ水。
「阿蘇のメイスイ」って裏に書いてある。
なんかいいですね、水。
もったいなくて飲めない。

Postgresを厳しい環境で使うという事について話をした谷田豊盛さんの講演はわかりやすかったです。
他の機会でなんらかのセミナーに参加していろんな人の講演を聞いた事があるんですけど、それらと比較すると谷田さんの講演は要点がうまくまとまってて伝えたいことがよくわかるんで、これは上手い部類に入るんだろうなーなんて感心してました。
自分が講演するときの参考にしようと思ったけど、講演する機会が無いんでプレゼンする時に参考にしようと思ったけど、プレゼンする機会もないと気付く。

Postgresを使って大規模システムを運営するために知っておかなくちゃいけないこと&テクニック&問題点などなど。
谷田さん自身Postgresを極めてる方なんで、経験者のためになるお話を聞けました。

たまにはセミナーに参加するのもいいもんですね。

プログラム | 23:36 | comments(0) | trackbacks(1) | ↑TOP | BlogRanking
プログラムを使い始めた歳
プログラマの皆さんって何歳からプログラムを始めたんでしょうか?

という自分の素朴な疑問。

就職先で始めた人、小さい頃から好奇心で始めた人、趣味で始めた人、学生時代に授業で始めた人、いろいろいるとは思いますが。
自分は20歳の時に就職先で初めて触れたんですが、小さな頃から趣味でプログラミングしてきたような人って相当出来るプログラマなんだろうなと勝手に思ってみる。

周りの人達は専門学校でプログラミングを初めて触ったという人がほとんどです。
動機は「ゲームを作りたいから」がほとんどでした。

世のプログラマの皆さんのプログラマになるきっかけが気になる今日この頃。

これ読んでる人ってほとんどいないと思うけど、きっかけ&始めた歳をコメントに残してくれるとうれしいナリ。

プログラム | 19:09 | comments(0) | trackbacks(0) | ↑TOP | BlogRanking
mysqlで全文検索
100000件以上のレコードでのキーワード検索が遅くて困ってます。
ある2つのカラムのどちらかに指定キーワードがあればselectするという条件です。
こんな感じでselectしてます。

mysql> select count(*) from search where text like '%mysql%' or title like '%mysql%';

likeで%を前後に使用してるんでインデックスが適応されない検索をしてます。
結果表示に2〜6秒かかるんで体感出来るくらい遅いです。

そこで全文検索なるものを使用しようかと思いました。
MATCH()関数で検索対象のカラムを指定します。
でも対象カラムはfulltextインデックスがはられていないとダメなんです。
そして検索文字列はAGAINST()で指定します。

全文検索はMySQL3.23.23以上のバージョンから使用可能みたいです。
MyISAMテーブルのみに使用できます。

早速テストしてみました。
使用データーベースはmysql4.0.23で、検索対象テーブルのレコード数は70000件を用意して、2つのカラムを対象にキーワード検索をします。
とりあえず以下のテーブルを作る。

create table search (
   title char(128) not null default '',
   text char(255) not null default ''
)type=myisam;

テーブル作ったら70000件のデータを挿入。
で、fulltextインデックスをはる。

alter table search add fulltext(title);
alter table search add fulltext(text);

まずは普通にlikeを使用して「mysql」という単語を両方のカラムを対象に検索。

mysql> select count(*) from search where text like '%mysql%' or title like '%mysql%';
+----------+
| count(*) |
+----------+
|    20000 |
+----------+
1 row in set (1.39 sec)

次にMATCH()とAGAINST()を使用した全文検索。

mysql> select count(*) from search where match(title) against('mysql') or match(text) against('mysql');
+----------+
| count(*) |
+----------+
|    20000 |
+----------+
1 row in set (0.46 sec)

結果、53秒速くなりました。

次は、両方のカラムを複合インデックスにしてやってみます。
まず、すでにはられているインデックスを削除。

drop index title on search;
drop index text on search;

改めてfulltextの複合インデックスをはる。

alter table search add fulltext(title,text);

で、全文検索。

mysql> select count(*) from search where match (title,text) against ('mysql');
+----------+
| count(*) |
+----------+
|    20000 |
+----------+
1 row in set (0.23 sec)

通常のインデックスと比べると、23秒速くなりました。
2倍速くなるのは結構な結果ですね。

でもこの全文検索は日本語には対応してません。
実際に日本語を含むデータで検索してもヒットしなかったです。
完璧に英語のみ対応らしいです。
英語のように単語がスペースで区切ってある文字列を対象にしているので、単語がスペースで区切られない日本語はダメみたいです。
どうしても日本語で全文検索をしたいときは、日本語を英語のように単語ごとに区切ってデータの整形をしなくちゃいけないですね。

と、言うわけで日本語が使えないんじゃ使いもんにならないやという事になりましたよ。
日本語整形プログラム作るのもめんどいしなーみたいな。


参考ページ
http://www.itmedia.co.jp/enterprise/0307/03/epn41.html
http://dev.mysql.com/doc/mysql/ja/Indexes.html
http://dev.mysql.com/doc/mysql/ja/Fulltext_Search.html
http://dev.mysql.com/doc/mysql/ja/Fulltext_Restrictions.html
http://dev.mysql.com/doc/mysql/ja/Fulltext_Fine-tuning.html
http://dev.mysql.com/doc/mysql/ja/Fulltext_TODO.html

プログラム | 13:59 | comments(2) | trackbacks(0) | ↑TOP | BlogRanking
PHPに複数の深刻な脆弱性
PHPに複数の深刻な脆弱性が見つかったらしいです。
一連の脆弱性はPHP4.3.9以前と5.0.2以前に存在する、とかいってPHP使ってるシステムほとんどじゃん。
できるだけ早くそれらのバグを修正した最新版である「4.3.10」又は「5.0.3」へアップグレードするべし、との事です。

おい!年末に何してくれんねん!
年末って事で普通に忙しいのによけいな仕事を増やしてくれるな。
大急ぎでメンテナンスしてPHPの再インストールしました。
他の会社も再インストール作業でワラワラしてるんでしょうか。

前までPHP4.2.2を使ってたんですが、バージョンが上がってから文法チェックが厳しくなっていて、曖昧な書き方をしているところでエラーが出ちゃいました。
曖昧な書き方はダメですね。
これを機にいっせいに曖昧なところを修正しました。
良い機会だったなあ。

プログラム | 00:08 | comments(0) | trackbacks(0) | ↑TOP | BlogRanking
プログラムでよくやる間違い
プログラミングしてると間違った書き方をしてエラーをだしたりするときがあります。
エラーをださなくても動作が怪しくなったりするときがあります。
その原因がしょうもない事だったりしちゃう時があるんですよ。
アホかと思うようなこと多いです。
例えばこんな風。
ちなみにphpです。

間違い1
  1| <?
  2|
  3| print($str)
  4|
  5| ?>
[EOF]

間違い2
  1| <?
  2|
  3| if($str = "test")
  4| {
  5|  print($str);
  6| }
  7|
  8| ?>
[EOF]

間違い3
  1| <?
  2|
  3| if($num)
  4| {
  5|  print($num);
  6|
  7| ?>
[EOF]

間違い4
  1| <?
  2|
  3| for($i = 0; $i < 10; ++$i)
  4| {
  5|  for($i = 0; $i < 20; ++$i)
  6|  {
  7|    $buf[$i][$j] = $j;
  8|  }
  9| }
10|
11| ?>
[EOF]

間違い5
  1| <?
  2|
  3| header("Locaton: http://www.yahoo.co.jp/");
  4|
  5| ?>
[EOF]

間違い6
  1| <?
  2|
  3| $fp = fopen("text.txt");
  4| flock($fp,LOCK_SH);
  5| $buf = fread($fp,filesize("text.txt"));
  6| flock($fp,LOCK_UN);
  7| fclose($fp);
  8|
  9| ?>
[EOF]

なんていうか、ほんとにしょうもなさすぎて涙が出る思いですね。
お前はそんなでメシ食ってていいのかというかなんというか。
いや、大丈夫です。
デバッグちゃんとしてますから。




たぶん。

プログラム | 21:51 | comments(0) | trackbacks(0) | ↑TOP | BlogRanking
カウンターを壊れにくくしよう
おもしろいくらいにカウンターが壊れるんですよ。
こりゃいかんという事でソースを見直してみました。
phpで作ってます。
まずは元のソース。

[ver.1]
  1| $fp = fopen("./count.txt","r");
  2| flock($fp,LOCK_SH);
  3| $count = fgets($fp,1024);
  4| flock($fp, LOCK_UN);
  5| fclose($fp);
  6|
  7| $count = $count + 1;
  8|
  9| $fp = fopen("./count.txt","w");
10| flock($fp,LOCK_EX);
11| fputs($fp,$count);
12| flock($fp,LOCK_UN);
13| fclose($fp);
14|
[EOF]

これはやっぱりあれですかね。
読み込んでカウントして書き込む前に、ちがうプロセスがカウントされる前の数字を読み込むんでカウンター数値が変になるんですかね。

Aプロセスが1〜5行目でカウンター数値を読み込む。
仮にその数値が10だとする。
Aプロセスが7行目でプラスして11にする。
Aプロセスが11にした数値を9〜13行目でカウンターファイルに書き込む前にBプロセスが1〜5行目でカウンター数値を読み込む。
その数値はまだ10のままなので10を読み込む。
Aプロセスが9〜13行目を実行して11という数値をカウンターファイルに書き込む。
Bプロセスが7行目で数値にプラスして11にする。
Bプロセスが9〜13行目でカウンターファイルに11を書き込む。
と、AプロセスとBプロセスがアクセスしてるんでカウントは2回されて12になるはずですが、上記のような事がおこっているんで実際は11になっていると思われ。

で、実際そうなるか試してみました。

[test1]
  1| for($i = 0; $i < 10000; ++$i)
  2| {
  3|   $fp = fopen("./count.txt","r");
  4|   flock($fp,LOCK_SH);
  5|   $count = fgets($fp,1024);
  6|   flock($fp, LOCK_UN);
  7|   fclose($fp);
  8|
  9|   $count = $count + 1;
10|
11|   $fp = fopen("./count.txt","w");
12|   flock($fp,LOCK_EX);
13|   fputs($fp,$count);
14|   flock($fp,LOCK_UN);
15|   fclose($fp);
16| }
17|
[EOF]

ver.1のソースをそのまんま使ってます。
コレをほぼ同時に2つの違うプロセスに実行させます。
カウンターファイルの数値は0から始めます。
するとどうでしょう。
本来なら20000という数値になっていてほしいですが、結果は5226といった数値になりました。
全然だめですねー。

そこでちょっと書き方を変えてみました。
読み込みと書き込みを一緒にロックしてみました。

[ver.2]
1| $fp = fopen("./count.txt","r+");
2| flock($fp,LOCK_EX);
3| $count = fgets($fp,1024);
4| $count = $count + 1;
5| rewind($fp);
6| fputs($fp,$count);
7| flock($fp,LOCK_UN);
8| fclose($fp);
9|
[EOF]

で、またテストしてみました。

[test2]
  1| for($i = 0; $i < 10000; ++$i)
  2| {
  3|   $fp = fopen("./count.txt","r+");
  4|   flock($fp,LOCK_EX);
  5|   $count = fgets($fp,1024);
  6|   $count = $count + 1;
  7|   rewind($fp);
  8|   fputs($fp,$count);
  9|   flock($fp,LOCK_UN);
10|   fclose($fp);
11| }
12|
[EOF]

そして結果は、18171になりました。
test1よりは20000に近づいていますよ。
しかあし、まだダメですよ。
じゃあ、これならどうだっ!

[ver.3]
  1| $lock_fp = fopen("./lock.txt","w");
  2| flock($lock_fp,LOCK_EX);
  3|
  4| $fp = fopen("./count.txt","r+");
  5| flock($fp,LOCK_EX);
  6| $count = fgets($fp,1024);
  7| $count = $count + 1;
  8| rewind($fp);
  9| fputs($fp,$count);
10| flock($fp,LOCK_UN);
11| fclose($fp);
12|
13| flock($lock_fp,LOCK_UN);
14| fclose($lock_fp);
15|
[EOF]

こうなったらロックファイルを使ってやる!ということですよ。
そしてテスト。

[test3]
  1| for($i = 0; $i < 10000; ++$i)
  2| {
  3|   $lock_fp = fopen("./lock.txt","w");
  4|   flock($lock_fp,LOCK_EX);
  5|
  6|   $fp = fopen("./count.txt","r+");
  7|   flock($fp,LOCK_EX);
  8|   $count = fgets($fp,1024);
  9|   $count = $count + 1;
10|   rewind($fp);
11|   fputs($fp,$count);
12|   flock($fp,LOCK_UN);
13|   fclose($fp);
14|
15|   flock($lock_fp,LOCK_UN);
16|   fclose($lock_fp);
17| }
18|
[EOF]

で、結果。
祝20000!!!!

ちなみにver.1とロックファイルの組み合わせでもしっかり20000でした。
でもfopenしてる回数が多いんでtest3と比べると3倍位の遅さでした。
要するにカウンター壊したくないんならロックファイルを使えやということでしょうかね。

テスト環境はこんな感じ。
OS:Windows 2000
言語:PHP4.1.2

テスト環境を変えたらtest2でも正常に20000になりました。
OS:FreeBSD 4.6
言語:PHP4.3.9
OSがunixだとflockの仕様が変わってくるんですかね?

もっとスマートで良い方法がありましたらおせーて下さい。

プログラム | 13:44 | comments(2) | trackbacks(0) | ↑TOP | BlogRanking
httpd.core
apacheのhttpd.confの設定を変更してapacheを再起動すると、あれ?起動しない。
おかしいなと、apacheを起動させて再度再起動をかけるとちゃんと再起動をした。けど、続けて再起動をかけるとまた起動しなくなる。
う〜ん?
何気なくlsコマンドで階層の一覧を見てみると

httpd.core

httpdがcore吐いてますよ!
あんた何吐いてんの!
とりあえずapacheのエラーログを見て見よう。

view /usr/local/apache/logs/error_log

[Wed Nov 10 14:24:32 2004] [notice] SIGHUP received. Attempting to restart
httpd in free(): warning: modified (chunk-) pointer
[Wed Nov 10 14:24:32 2004] [notice] Apache/1.3.31 (Unix) PHP/4.2.2 configured
-- resuming normal operations
[Wed Nov 10 14:24:32 2004] [notice] Accept mutex: flock (Default: flock)
[Wed Nov 10 14:24:41 2004] [notice] SIGHUP received. Attempting to restart

1回目の再起動で「httpd in free(): warning: modified (chunk-) pointer」というワーニングが出るけどなんとか再起動できてます。
しかし、2回目の再起動でSIGHUPはかかってるけどapacheが起動したログが出ていません。

ちなみにdmesgコマンドを使うと
pid 27433 (httpd), uid 0: exited on signal 11 (core dumped)
という危険なメッセージが出てますよ。
んー、どういう事かよくわからないけどとりあえずcore吐いてますよね。

なんか変な設定にしちゃったかなー...。
もう一度設定を見直してみることに。
とりあえずphp.iniの見直しをします。
そしたらね、すごいのみつけちゃったんですよ。
php.iniのmbstring関係の設定部分↓

[mbstring]
mbstring.internal_encoding = pqss
mbstring.http_input = pass
mbstring.http_output = pass
mbstring.detect_order = pqss
mbstring.substitute_character = none;

ん?

mbstring.internal_encoding = pqss
mbstring.detect_order = pqss

あれ?

pqss

マジデ?
ちゃんとpassってなってるとこもあるのになんでここだけスペル間違ってるのか...。

この後は言うまでもなく、ちゃんと再起動してくれる事がうれしくてSIGHUPの乱れ打ちをしてました。
ちゃんと再起動してるよー、こんなに超連続再起動かけてるのにーという感じで。

プログラム | 01:30 | comments(0) | trackbacks(0) | ↑TOP | BlogRanking
apacheのhttpd.conf
apacheをインストールした後にphpをインストールして、ブラウザからphpの動作確認をしてみたらphpが動かないんですよ。
ダウンロード画面になっちゃうんですよ。

80番ポート以外にも他2つのポートを立ち上げてるんですが、80番ポートでは正常に動作するのに他のポートだとだめなんですよね。
httpd.confの中身を確認してちゃんとAddType application/x-httpd-php .phpと記述していることを確認してもだめでした。
よくよく見ると、httpd.conf内のLoadModuleとAddModuleにphpのモジュールが記述されてませんでした。
でも80番ポートには記述されているのに他ポートには記述されていないのはなんでだろと思ってたら、重大な事を思い出しました。

ポート分けをする際に/apache/confごと丸コピーしてるんですが、phpインストールするとphpモジュール記述がデフォルトのconfにしか記述されないという事に気が付きました。

そりゃそうですよね。(・e・)

プログラム | 13:38 | comments(0) | trackbacks(0) | ↑TOP | BlogRanking
qmail Temporary error on maildir delivery
qmailをインストールしてMaildir形式にしてchangeユーザーを作ってchange宛にテストメールを投げたんですけど、届かないんですよね。
/var/log/maillogを見ながらメールを投げるとTemporary error on maildir deliveryなるエラーが出てました。
changeユーザーのホームディレクトリのパーミッションやオーナーも変更したし、/var/qmail/rcの内容もしっかりチェックしたのになぜだろう。

ふと、自分の打ったコマンドを見てみると
chown change:change /home/change/Maildir
ん?
chown change:change
おお
chown -R change:change
ですよ。
バカでしたねー(・e・)

プログラム | 14:46 | comments(0) | trackbacks(0) | ↑TOP | BlogRanking