月別アーカイブ: 2011年2月

PostgreSQL Conference 2011 Tokyoに参加してきました。

簡単ですが、レポートします。

有料カンファレンスですが、チケット完売ということで、一部セッションは立ち見でした。どんな人が来るのかと思っていましたが、参加者は、スーツの人も私服の人もいました。日本PostgreSQLユーザ会は頑張っているんだなという印象を受けました。

PostgreSQLを活用した国内初の流通小売業向けSaaS型基幹システム

 当初はポスグレ7系を利用していたが、8.4に移行したという話です。
 かなりのデータ量を扱っているようで、vaccum reindex reanalyzeをするだけでも、ユーザ画面に影響が出ないようにするため、手動でテーブルごとに行う作業が9人で216時間を要するそうです。(これって、9*216時間という意味なのか、合計なのか不明)これだけ大きなデータだと、移行にpgdump,pgrestoreを使うとダウンタイムが長すぎる…そういうことで、Slowlyを使った非同期レプリケーションで移行する方法を採用したとのこと。7系から8.4に移行したことで、600分のバッチ処理が200分で処理できるようになり、ユーザからの問い合わせも減ったそうです。

 相当苦労したということが伝わりました。貴重な話を聞けたと思います。

PostgreSQL 9.0 ストリーミングレプリケーションの実力

 PostgresQL 9.0のレプリケーション機能のベンチマーク発表です。レプリケーション環境を構築して台数を増やしたとき、参照は早くなりますが、更新は遅くなります。その更新系の性能低下は、ほぼ一次関数的らしいです。(2〜12ノードにおいて)
遅くなる原因:

  • CPUでもロック待ちではない
  • 大きな要因は見られない

⇒ IO衝突、ネットワーク混雑、WALセンダーのCPU取り合い等が複合的に起こっているのでは?とのこと。

PostgreSQL アーキテクチャ入門

 ものすごい人気セッション!立ち見、満員電車状態でした。(´Д`;)
 名前だけは聞く程度だった「共有バッファ」「postmaster」などの意味がわかりました。
 パフォーマンス改善の手順について、log_min_durationオプションや、pgFouineを今度使ってみようと思いました。

徹底比較 PostgreSQL vs MySQL

 日本での利用率でMySQLがPostgreSQLを上回ったらしい。負けた要因は!?

  • 「PostgreSQLが遅いというのは事実ではない」(MySQLもInnoDBを使えば劇的に速くはない)
  • PostgreSQLはJIS2004対応!一方、MySQLの日本語対応はあまりやる気がないらしい。
  • Oracleに買収されてから、MySQLの商用版が高くなったらしい
  • レプリケーションはMySQLの方が就實している。PostgreSQLはこれから実績が増えることを期待!

結局どちらが有利というわけではなく、得意不得意がありますということでした。全体的にレプリケーションの話が多かったです。トランザクション周りがポスグレの方が充実しているという話が聞かれなかったのが予想と外れました。

書き込みスケールを実現したPostreSQL-XCクラスタ

 PostgreSQLサーバを複数並べて、更新系も参照系も分散できるクラスタ環境を作る技術で、アプリケーション側からは、ほとんど普通のPostgreSQLに見えるということです。夢のようです。
 トリガーと、GTM(トランザクション制御ノード)のフェイルオーバー機能が開発中とのことです。
 テーブルごとに、レプリケーション(参照が速くなる。マスタ向け)するか、テーブル分割するか(更新が速くなる。トランザクション向け)を選択するらしいです。
 開発も精力的に行われているみたいです!今後に期待!

Let's PostgreSQL

 こんなサイトがあったなんて知らなかった!
 http://lets.postgresql.jp/

ライトニングトーク

 SQLはLLだそうです。かわいいですね。


JavaScript+HTMLのみでテキストボックスのplaceholder実装メモ

よくあるWebフォームの表現で、入力欄が空欄の時は「入力してください」のようなデフォルトの文言が出ていて、フォーカスを当てると空欄になるような仕掛けがあります。この表現は、placeholderとか、watermarks(透かし)と呼ばれるようで、HTML5の場合は標準機能のようです。また、jqueryを使用している場合はプラグインもあるようですが、既存のページで対応しなければいけない場合のための、ライブラリなしの実装しました。地味にはまったので、メモを残します。

なお以下の実装を導き出す際、@Otchyさんに助言を参考にさせていただきました。ありがとうございます。
http://twitter.com/otchy/status/37740505953468416
http://twitter.com/otchy/status/37742189345775616

実装手順

例えば備考フォームを作ろうとしたとします。

<html><body>
<form name="form1" method="GET" action="http://www.google.com">
<textarea name="biko"></textarea>
<input type="submit">
</form>
</body></html>

bikoの下にダミーのテキストエリアを配置し、displayをnoneにします。

<textarea name="biko_dummy" style="display: none">ご要望などはこちらに入力してください。</textarea>

これでは初期表示時に、ダミーが表示されません。元のHTMLをいじって、

<textarea name="biko" style="display: none"></textarea>
<textarea name="biko_dummy">ご要望などはこちらに入力してください。</textarea>

このようにすれば、問題ないですが、万が一、JavaScriptが動かなかった場合、メインが表示されなくなってしまいます。そこで、この書き方はせず、JavaScriptで以下のようにします。

document.forms.form1.biko.onblur();

ところが、この書き方ではIE8では、「戻る」ボタンがうまく動きませんでした。戻るボタンの時にJavaScriptが走ってしまい、その時点では、まだbikoの値がロードされていないようで、必ずダミーが出現してしまいます。

以下のようにすることで回避できました!
setTimeout(function() {document.forms.form1.biko.onblur()}, 10);

if (window.attachEvent) {
window.attachEvent('onload', function() {document.forms.seisanForm.biko.onblur();});
} else {
document.forms.seisanForm.biko.onblur();
}

完成コード

<html>
<body>
<form name="form1" method="GET" action="http://www.google.com">
<textarea name="biko"></textarea>
<textarea name="biko_dummy" style="display: none">ご要望などはこちらに入力してください。</textarea>
<input type="submit">
</form>
<script type="text/javascript">
function onblurForm1Biko() {
   if (this.value == '') {
       this.style.display = 'none';
       this.form.biko_dummy.style.display = 'inline';
   }
}
function onfocusForm1BikoDummy() {
   this.form.biko.style.display = 'inline';
   this.style.display = 'none';
   this.form.biko.focus();
}
document.forms.form1.biko.onblur = onblurForm1Biko;
document.forms.form1.biko_dummy.onfocus = onfocusForm1BikoDummy;
if (window.attachEvent) {
   window.attachEvent('onload', function() {document.forms.seisanForm.biko.onblur();});
} else {
   document.forms.seisanForm.biko.onblur();
}
</script>
</body>
</html>

今回の場合、フォーム送信の時に "biko_dummy"の値も送信されてしまう問題があり、それを回避する場合は、textareaではなく、spanかなにかにすれば良いのですが、そうすると、デザイン調整とか、onfocusが使えないなど面倒なところもあるので、今回は上記実装で妥協しました。

以下、動作するサンプルです。

http://s-ishigami.appspot.com/files/placeholder.html

2011/02/18追記

setTimeoutよりもonloadの方が美しいと指摘を頂いたので、修正しました。ただ、既にonloadが使われている場合に厄介なので、attachEventを、(今回はIEだけの問題なので)存在チェック付きで使用しました。

やはり、jQuery使いたいですよね。


Javaによるお気楽なサンドボックス環境の作り方(セキュリティーマネージャ)

Javaで #appengine のようなサンドボックス環境を作る場合、SecurityManagerを使用するのがよさそうです。

http://itref.fc2web.com/java/security.html

具体的には、ポリシーファイルというものを書くという形になります。

(以下は転載)

grant {
permission java.util.PropertyPermission "test_prop", "write,read";
permission java.io.FilePermission "c:/temp/test.txt", "read,write";
//permission java.io.FilePermission "<>", "read,write";
};

しかし、今時のWebアプリなら、実行環境ごとに設定をお願いするのではなく、warをデプロイするだけで、必要な設定はなされていてくれる方がありがたいです。また、policyファイルのような外部ファイルを使うのではなく、純粋にJavaだけで制御すればデバッガもろもろが使えて便利ですよね?

policyファイルを使用しない方法は、java.lang.SecurityManager を独自にオーバーライドすることで実現できます。

http://java.sun.com/javase/ja/6/docs/ja/api/java/lang/SecurityManager.html

そして、こんな感じにします。

public class MySecurityManager extends SecurityManager {
@Override
public void checkExit(int status) {
throw new SecurityException("system exit is not supported.");
}
}
System.setSecurityManager(new MySecurityManager());

しかし、これだと、環境にセキュリティーマネージャが設定されている場合は、その実装が殺されてしまいます。ということは、セキュリティーが考慮された環境でこれを行った場合、ヘタをすると、セキュリティーを低下させてしまいかねません。

※もちろん、よく設定された環境では、セキュリティマネージャの設定自体が許されない可能性もあります。

そう思うと気が重いことです。なかなか手をつけられません。

そこで、既存のセキュリティマネージャを生かしつつ、独自のセキュリティーチェックをJavaだけで実装しようとする場合は、以下のようにすれば良さそうです。

public class NullSecurityManager extends SecurityManager {
@Override
public void checkPermission(Permission perm, Object context) {
// なにもしない
}
@Override
public void checkPermission(Permission perm) {
// なにもしない
}
}
public class MySecurityManager extends NullSecurityManager {
private SecurityManager innerSecurityManager;
public MySecurityManager(SecurityManager innerSecurityManager) {
if (innerSecurityManager == null) {
innerSecurityManager = new NullSecurityManager();
}
this.innerSecurityManager = innerSecurityManager;
}
@Override
public void checkPermission(Permission perm) {
innerSecurityManager.checkPermission(perm);
}
@Override
public void checkPermission(Permission perm, Object context) {
innerSecurityManager.checkPermission(perm, context);
}
@Override
public void checkCreateClassLoader() {
innerSecurityManager.checkCreateClassLoader();
}
public void checkExit(int status) {
innerSecurityManager.checkExit(status);
throw new SecurityException("system exit is not supported.");
}
// 以下あらゆるメcheck系メソッドを委譲
}

あとは、Servletの起動時に

try {
SecurityManager securityManager = System.getSecurityManager();
if (!(securityManager instanceof MySecurityManager)) {
System.setSecurityManager(new MySecurityManager(securityManager));
}
} catch (SecurityException e) {
System.out.println("cannot set my SecurityManager");
}

こんな感じで動きました。