SELECT relname, relkind, to_char(reltuples, '999,999,999') as rows, to_char(pg_relation_size(relname), '999,999,999,999') as bytes FROM pg_class WHERE relnamespace = (SELECT oid FROM pg_namespace WHERE nspname='public') order by bytes desc;
概要
StringBuider で append() を使い1文字を追加するとき、
sb.append('\t');
のように char 型を追加するときと
sb.append("\t");
のように文字列型で追加するときに性能差を調査した。結果
| 追加データ | 実行時間 [s] |
|---|---|
| '\t' | 2.165 |
| "\t" | 7.788 |
概要
PostgreSQL 上に作成したテーブルに対し、Java で時刻を timestamp 型ではなくミリ秒(long 値)のまま格納した場合、それを select で timestamp 型として取り出すには以下のように SQL を記述する。
SELECT
(lastaccess / 1000) :: text :: interval + '1970-01-01' :: timestamp
FROM
table1;
lastaccess は bigint 型のカラム。これを1000分の1して秒単位にし、 epoch 秒(グリニッジ標準時間1970年1月1日00:00:00からの経過秒数) に足している。
例: DB に格納された tomcat のセッションでサイズの大きいものを見つける
次のような SQL を実行する。SELECT length(data) as len, session_id, (lastaccess / 1000) :: text :: interval + '1970-01-01' :: timestamp FROM tomcat_sessions ORDER BY len desc LIMIT 20;
概要
Windows7で Eclipse 3.3 を動作したときに「パッケージ・エクスプローラ」ビューが自動的に横スクロールするのを停止する方法について説明。32bit, 64 bit 環境の違いなく簡単に解決できるので便利。
多分 Vista でも同じ方法で解決する。
背景
Windows7(と Vista)でEclipseを利用時、イライラする現象がある。画面左側の「パッケージ・エクスプローラ」ツリービューにおいて、深いパッケージ階層にアクセスしている時に、勝手に横スクロールする。

十分な横幅の画面で作業していれば、このビューを横に広げてこの問題を回避できるが...。
この新たな機能は Windows Vista からツリービューに搭載されたものらしい。。。
せめて挙動を選択できるようにして欲しかった。
32bit ユーザなら Explorer Construction で!
Explorer Constructionというツールを使うことで、この横スクロールを無効化できるらしい。ソフト起動後、「水平方向の自動スクロールを無効にする(A) 」にチェックを入れるだけ。
残念ながら 64bit 環境では動作しない。本当に残念...。
Windows 互換モードで実行することで 64bit でも解決!
しばらく探しまわって、やっと解決法を見つけた。 ⇒disable dynamic horizontal scrolling in Vista内容は簡単。「Eclipse を Windows XP 互換モードで動かすだけ」でした。
Eclipse のショートカットを作成し、プロパティを表示。 「互換性」タブで「互換モードでこのプログラムを実行する」にチェックを入れ、 「Windows XP (Service Pack 3)」を選択するだけでよい。

この方法は Eclipse だけでなく他のアプリケーションでも適用できる。
概要
PostgreSQLの各プロセスがどのテーブルでどの種類のロックを行っているか調べる方法について説明。さらに、そのプロセスを下記手順で終了することで、ロックしていた処理を強制的に中断できる。
手順
プロセスIDの確認
コマンドラインなどで、次のSQLを実行する。
SELECT l.pid, db.datname, c.relname, l.locktype, l.mode
FROM pg_locks l
LEFT JOIN pg_class c ON l.relation=c.relfilenode
LEFT JOIN pg_database db ON l.database = db.oid
ORDER BY l.pid;
pid がプロセスIDを意味する。
プロセスの停止
プロセスIDが分かったら、次のSQLでプロセスを停止できる。SELECT pg_cancel_backend(プロセスID);
概要
前回 は、Windows 上で起動した Java プロセスを snmp で監視する方法を説明した。今回は Linux 上で起動した Tomcat プロセスのメモリを監視する方法について説明する。
動作環境
| 項目 | 値 |
|---|---|
| OS | CentOS 5 |
| Java | JDK 6 update 10 |
| Tomcat | 6.0.20 |
tomcat 起動時の設定
Tomcat を起動する時の CATALINA_OPTS 変数に次の記述を追加する。例えば、/etc/tomcat6/tomcat6.conf で次のように記述する。
CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.snmp.port=1161 -Dcom.sun.management.snmp.acl.file=/etc/tomcat6/snmp.acl"
/etc/tomcat6/snmp.acl 作成
ファイルを作成する。
acl = {
{
communities = public
access = read-only
managers = localhost
}
}
さらに、snmp.acl のパーミッションを 600 に変更する。# chown roo:root snmp.acl # chmod 600 snmp.aclここまで設定が終わったら、Tomcat を起動する。
# service tomcat6 start
MIB ファイルを置く
/usr/share/snmp/mibs/JVM-MANAGEMENT-MIB.mib を作成する。
# cd /usr/share/snmp/mibs/
# lftpget http://java.sun.com/j2se/1.5.0/docs/guide/management/JVM-MANAGEMENT-MIB.mib
# lftpget http://java.sun.com/j2se/1.5.0/docs/guide/management/JVM-MANAGEMENT-MIB.mib
/etc/snmp/snmp.conf 設定
次に snmpd の設定。このファイルの最後へ記述を追加する。
proxy -m /usr/share/snmp/mibs/JVM-MANAGEMENT-MIB.txt -v 2c -c public localhost:1161 .1.3.6.1.4.1.42.2.145
記述を追加したら、snmpd を再起動する。
# service snmpd restart
動作確認
$ snmpwalk -v 2c -c public localhost .1.3.6.1.4.1.42.2.145
出力結果をカスタマイズ
数字で構成される OID 値を文字列に変更できる。上記の手順で mib ファイルを snmpwalk を実行するホストに置いた後、次のように環境変数を設定する。
.bashrc などに書いておくとよい。
$ export MIBS=ALL
$ snmpwalk -v 2c -c public localhost .1.3.6.1.4.1.42.2.145
$ snmpwalk -v 2c -c public localhost .1.3.6.1.4.1.42.2.145
参考
概要
Javaでwebサイトを運用し、ある程度規模が大きくなってくるとメモリ管理で悩まされる。安定、高速なwebサイトを目指すためにはメモリ関連のモニタリングとチューニングが必要になってくる。
ガベージ・コレクション関連のログ出力設定を行う方法は簡単だが、nagios などで監視を行い、閾値に達したらアラート・メールで通知してくれると便利である。
今回は Java の snmp 監視を有効にする設定手順について説明する。
開発環境
| 項目 | 値 |
|---|---|
| OS | Windows XP Pro SP3 |
| IDE 環境 | Eclipse 3.4.1(Preiades All in One) |
| Java | JDK 6 update 10 |
Windows 環境での設定手順
概要
Windows 上で起動中の Eclipse から Java プログラムを起動し、そのプロセスを snmp で監視できるよう、設定を行う。プログラム例
次のようなプログラムを作成した。
public class Test {
public static void main(String[] args) throws InterruptedException {
int count = 0;
for (;;) {
Thread.sleep(1000);
count++;
System.out.println(count);
}
}
}
とりあえず1回実行してみる。[実行] メニュー ⇒ 実行 ⇒ Java アプリケーション
起動オプション設定
1回実行した後、今度は実行構成を開く。[実行] メニュー ⇒ 実行構成
[引数] タブを選択し、「VM引数」のところに次の文字列を入力する。
-Dcom.sun.management.snmp.port=161 -Dcom.sun.management.snmp.acl.file=c:/snmp.acl -Dcom.sun.management.config.file=c:/management.properties
設定ファイルのコピー
次に、C:\Program Files\Java\jre6\lib\management の下にある、次の2つのファイルを C:\ にコピーする。
- management.properties
- snmp.acl.template
snmp.acl.template は snmp.acl に名前を変える。
設定ファイルの修正
c:\snmp.acl
ホスト 172.16.1.2 からコミュニティ名「public」で snmp 読み込みを受け付ける場合は、次のように記述する。
acl = {
{
communities = public
access = read-only
managers = 172.16.1.2
}
}
c:\management.properties
Java 起動時、デフォルト設定では localhost で 161 ポートを listen する。別のホストから snmp を受け付けるには、次のように Java プログラムを起動するホストの IP アドレスを設定する。com.sun.management.snmp.interface=172.16.1.3
アクセス権の修正
エクスプローラで c:\snmp.acl 上で右クリック、[プロパティ] を選択する。[セキュリティ] タブを開き、[詳細設定] ボタンを押す。
「子オブジェクトに適用するアクセス許可エントリを親から継承し、それらをここで明示的に定義されているものに含める」についているチェックを外す。
「アクセス許可エントリ」から、自分の名前以外を全て削除する。
Administrator や他のユーザからのアクセス権が残っていると、Java プログラム起動時に次のようなエラーメッセージが出てしまう。
エラー: パスワードファイルの読み取りアクセスは制限する必要があります。: c:/snmp.acl
これで準備完了。
サンプルプログラムを起動したあと、snmp アクセスを許可したホスト(上記の例だと 172.16.1.2) から次のようにアクセスしてみる。
$ snmpwalk -v 2c -c public 172.16.1.3 .1 -On | less次のような内容が出力される。
.1.3.6.1.4.1.42.2.145.3.163.1.1.1.1.0 = Gauge32: 729 .1.3.6.1.4.1.42.2.145.3.163.1.1.1.4.0 = INTEGER: 1 .1.3.6.1.4.1.42.2.145.3.163.1.1.2.1.0 = Gauge32: 0 .1.3.6.1.4.1.42.2.145.3.163.1.1.2.2.0 = INTEGER: 1 .1.3.6.1.4.1.42.2.145.3.163.1.1.2.3.0 = INTEGER: 2 .1.3.6.1.4.1.42.2.145.3.163.1.1.2.100.1.2.1 = STRING: "CodeCacheManager" .1.3.6.1.4.1.42.2.145.3.163.1.1.2.100.1.2.2 = STRING: "Copy" .1.3.6.1.4.1.42.2.145.3.163.1.1.2.100.1.2.3 = STRING: "MarkSweepCompact" .1.3.6.1.4.1.42.2.145.3.163.1.1.2.100.1.3.1 = INTEGER: 2 .1.3.6.1.4.1.42.2.145.3.163.1.1.2.100.1.3.2 = INTEGER: 2 .1.3.6.1.4.1.42.2.145.3.163.1.1.2.100.1.3.3 = INTEGER: 2 .1.3.6.1.4.1.42.2.145.3.163.1.1.2.110.1.2.1 = STRING: "Code Cache" .1.3.6.1.4.1.42.2.145.3.163.1.1.2.110.1.2.2 = STRING: "Eden Space" .1.3.6.1.4.1.42.2.145.3.163.1.1.2.110.1.2.3 = STRING: "Survivor Space" .1.3.6.1.4.1.42.2.145.3.163.1.1.2.110.1.2.4 = STRING: "Tenured Gen" .1.3.6.1.4.1.42.2.145.3.163.1.1.2.110.1.2.5 = STRING: "Perm Gen" .1.3.6.1.4.1.42.2.145.3.163.1.1.2.110.1.2.6 = STRING: "Perm Gen [shared-ro]" .1.3.6.1.4.1.42.2.145.3.163.1.1.2.110.1.2.7 = STRING: "Perm Gen [shared-rw]" .1.3.6.1.4.1.42.2.145.3.163.1.1.2.110.1.3.1 = INTEGER: 1 .1.3.6.1.4.1.42.2.145.3.163.1.1.2.110.1.3.2 = INTEGER: 2 .1.3.6.1.4.1.42.2.145.3.163.1.1.2.110.1.3.3 = INTEGER: 2 .1.3.6.1.4.1.42.2.145.3.163.1.1.2.110.1.3.4 = INTEGER: 2 .1.3.6.1.4.1.42.2.145.3.163.1.1.2.110.1.3.5 = INTEGER: 1 .1.3.6.1.4.1.42.2.145.3.163.1.1.2.110.1.3.6 = INTEGER: 1 .1.3.6.1.4.1.42.2.145.3.163.1.1.2.110.1.3.7 = INTEGER: 1 .1.3.6.1.4.1.42.2.145.3.163.1.1.2.110.1.4.1 = INTEGER: 2 .1.3.6.1.4.1.42.2.145.3.163.1.1.2.110.1.4.2 = INTEGER: 2 .1.3.6.1.4.1.42.2.145.3.163.1.1.2.110.1.4.3 = INTEGER: 2 .1.3.6.1.4.1.42.2.145.3.163.1.1.2.110.1.4.4 = INTEGER: 2 .1.3.6.1.4.1.42.2.145.3.163.1.1.2.110.1.4.5 = INTEGER: 2 .1.3.6.1.4.1.42.2.145.3.163.1.1.2.110.1.4.6 = INTEGER: 2 .1.3.6.1.4.1.42.2.145.3.163.1.1.2.110.1.4.7 = INTEGER: 2 .1.3.6.1.4.1.42.2.145.3.163.1.1.2.110.1.112.1 = INTEGER: 2 .1.3.6.1.4.1.42.2.145.3.163.1.1.2.110.1.112.2 = INTEGER: 1 .1.3.6.1.4.1.42.2.145.3.163.1.1.2.110.1.112.3 = INTEGER: 1 .1.3.6.1.4.1.42.2.145.3.163.1.1.2.110.1.112.4 = INTEGER: 2 .1.3.6.1.4.1.42.2.145.3.163.1.1.2.110.1.112.5 = INTEGER: 2 ...なお、-v で指定する SNMP バージョンは 2c を指定する必要がある。
1 だと、heap 値を取得できない。
参考情報
Sun から提供されている以下のドキュメントを参考。概要
BIG-IP + Linux 2台(CentOS 5) で DSR(Direct Server Retrun) 構成を行ったときの設定メモ。DSRとは
こちらの記事が分かりやすい。この記事にあるように、このままだと mac アドレスがあちこちにキャッシュされてしまい、いろいろ問題が出て少々やっかいだった。
次のように iptables と組み合わることで、簡単にこの問題を解決できる。
バックエンド設定
Linux サーバの /etc/sysconfig/iptables に対し、次の設定を行う。*filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] COMMIT # ================================================================= *nat -A PREROUTING -p tcp -d 172.16.100.1 -j REDIRECT COMMIT172.16.100.1 はロードバランサで設定した VIP アドレス。
背景 - ロック手法について
データベース更新時のロックの方法として、次の2種類が存在する。- 悲観的ロック (Pessimistic lock)
- 楽観的ロック (Optimistic lock)
データをより安全に更新・参照できるメリットがあるが、ロック待ちによるアプリケーションの性能低下要因となりやすい。
楽観的ロックは「自分が操作している情報は他人が同時に更新する可能性が低い」更新を行うのに向いたロック方法。
更新対象を本当に更新する段階までぎりぎりまでロックしない。
例えば、「一旦データを取得したあと、内容を変更して実際に変更しようとしたら、データ取得後に誰かが同じレコードを更新していた」というケースの場合、悲観的ロックであれば「データ取得時に行ロックを行い、誰も更新できない状況」を作ってから更新を行う。その間、他の更新処理は自分の処理が完了するまで待ち状態となる。
一方、楽観的ロックであれば、自分がデータ取得後に他人がデータを更新できてしまう。自分がその後に更新しようとすると JPA 利用時、 OptimisticLockException が発生する。
概要
JPA(Java Persistence API) 1.0では楽観的ロックのみサポートしている。2.0 からは悲観的ロックもサポートするらしい。Seasar2 + Hibernate + JPA 1.0 の構成において悲観的ロックでデータを更新したいと思い試行錯誤したが、意外とつまづいた。
EntityManager に lock() というメソッドがあって、write lock もできそうだが、うまくいかない。seasar がサポートしていないのか、設定がうまくいっていないのか...
結局、以下の方法で実現できた。
悲観的ロックによる更新方法
次のようなコードになる。
package jp.trasis.sample.service;
import javax.persistence.EntityManager;
import jp.trasis.sample.entity.User;
import org.seasar.extension.tx.annotation.RequiresNewTx;
import org.seasar.framework.container.annotation.tiger.Binding;
public class TestService {
@Binding
private EntityManager entityManager;
@RequiresNewTx
public void test(Long userId, String name) {
User user = (User) entityManager.createNativeQuery(
"select * from User_ where id=:userId for update", User.class)
.setParameter("userId", userId)
.getSingleResult();
user.setName(name);
entityManager.persist(user);
}
}
解説
@RequiresNewTx アノテーションにより、新たなトランザクションの中で更新処理を行う。まず、更新対象のエンティティを select ... for update により、行ロックを行いながら取得する。
この SQL は createNativeQuery() メソッドで実行する必要がある。crateQuery() で使用する HQL では、 for update 文は利用できない。
そしてエンティティに対して修正を行い、 persist() でコミットを行う。メソッドを抜けるときに実際に DB へのコミット処理が行われ、トランザクションが終了し、ロックも開放される。
概要
Eclispe 上で JavaScript(.js) ファイルに日本語を使うと、保存できなかったり、再度開くと文字化けしたりする。こちらのブログ記事 に、その対策方法が記載されている。
このブログによると、Eclipse に次の設定を行うことで解決できる。
動作確認環境
| 項目 | 内容 |
|---|---|
| Eclipse バージョン | 3.3.2 3.4.1 |
設定手順
エクスプローラで、次のファイルを編集する。workspace\.metadata\.plugins\org.eclipse.core.runtime\.settings\org.eclipse.core.runtime.prefs
次の内容を記述して Eclipse を再起動。
content-types/org.eclipse.wst.javascript.core.javascriptsource/charset=
プロジェクトごとに設定できるか?
複数人で開発しているときは、全員にこの設定をしてもらわないといけないし、Eclipse を新たなPCにインストールしたときも、この設定を行わないといけないので面倒...ということで、プロジェクトにこの設定を行うことができるかどうかを試した。
結論は、残念ながらできない。
プロジェクト直下にある .setting フォルダに org.eclipse.core.runtime.prefs ファイルを作成し、上記の記述を行ってみたが、反映されなかった。
Eclipse Pleiades All-in-one で対応してくれたらいいな...