Hatena::ブログ(Diary)

ablog このページをアンテナに追加 RSSフィード

2013-04-21

Oracle Database のサーバー・プロセスが通信する際にどのようなソケットオプションを使っているか調べる

環境

[root@localhost ~]# cat /etc/issue
Enterprise Linux Enterprise Linux Server release 5.5 (Carthage)
Kernel \r on an \m

[root@localhost ~]# uname -a
Linux localhost.localdomain 2.6.18-194.17.1.0.1.el5 #1 SMP Wed Sep 29 15:40:03 EDT 2010 i686 i686 i386 GNU/Linux
SQL> select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - Production
PL/SQL Release 11.2.0.2.0 - Production
CORE    11.2.0.2.0      Production
TNS for Linux: Version 11.2.0.2.0 - Production
NLSRTL Version 11.2.0.2.0 - Production
[oracle@localhost OPatch]$ ./opatch lsinventory
...
Installed Top-level Products (1): 

Oracle Database 11g                                                  11.2.0.2.0
There are 1 products installed in this Oracle Home.


There are no Interim patches installed in this Oracle Home.

strace でシステムコールをトレースする

[root@localhost ~]# ps -ef|grep [t]ns
oracle    3249     1  0 19:35 ?        00:00:00 /home/oracle/app/oracle/product/11.2.0/dbhome_2/bin/tnslsnr LISTENER -inherit
[root@localhost ~]# strace -tf -p 3249 -o strace.log
[root@localhost ~]# grep -i setsockopt strace.log
3250  20:12:35 setsockopt(14, SOL_SOCKET, SO_LINGER, {onoff=1, linger=900}, 8) = 0
3249  20:12:36 setsockopt(14, SOL_TCP, TCP_NODELAY, [1], 4) = 0
3601  20:12:36 setsockopt(14, SOL_TCP, TCP_NODELAY, [1], 4) = 0
3601  20:12:37 setsockopt(14, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0
3601  20:12:37 setsockopt(14, SOL_SOCKET, SO_SNDTIMEO, "\0\0\0\0\0\0\0\0", 8) = 0
3601  20:12:37 setsockopt(14, SOL_SOCKET, SO_RCVTIMEO, "\0\0\0\0\0\0\0\0", 8) = 0
3601  20:12:37 setsockopt(14, SOL_SOCKET, SO_KEEPALIVE, [0], 4) = 0
3250  20:12:40 setsockopt(14, SOL_SOCKET, SO_LINGER, {onoff=1, linger=900}, 8) = 0
3249  20:12:40 setsockopt(14, SOL_TCP, TCP_NODELAY, [1], 4) = 0
3603  20:12:40 setsockopt(14, SOL_TCP, TCP_NODELAY, [1], 4) = 0
3603  20:12:40 setsockopt(14, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0
3603  20:12:41 setsockopt(14, SOL_SOCKET, SO_SNDTIMEO, "\0\0\0\0\0\0\0\0", 8) = 0
3603  20:12:41 setsockopt(14, SOL_SOCKET, SO_RCVTIMEO, "\0\0\0\0\0\0\0\0", 8) = 0
3603  20:12:41 setsockopt(14, SOL_SOCKET, SO_KEEPALIVE, [0], 4) = 0



Oracle Net トレース・ファイルから確認する

  • Oracle Database の sqlnet.ora にトレース・レベルを設定する
[oracle@localhost ~]$ cat /home/oracle/app/oracle/product/11.2.0/dbhome_2/network/admin/sqlnet.ora 
TRACE_LEVEL_SERVER=16
[oracle@localhost trace]$ grep testc *
orcl_ora_3564.trc:2013-04-20 20:09:41.321368 : nsbasic_brc:2F 2A 20 74 65 73 74 63  |/*.testc|
orcl_ora_3566.trc:2013-04-20 20:09:42.272207 : nsbasic_brc:2F 2A 20 74 65 73 74 63  |/*.testc|
orcl_ora_3579.trc:2013-04-20 20:10:59.363429 : nsbasic_brc:2F 2A 20 74 65 73 74 63  |/*.testc|
orcl_ora_3581.trc:2013-04-20 20:11:04.073404 : nsbasic_brc:2F 2A 20 74 65 73 74 63  |/*.testc|
orcl_ora_3590.trc:2013-04-20 20:11:35.457958 : nsbasic_brc:2F 2A 20 74 65 73 74 63  |/*.testc|
orcl_ora_3601.trc:2013-04-20 20:12:37.614055 : nsbasic_brc:2F 2A 20 74 65 73 74 63  |/*.testc|
orcl_ora_3603.trc:2013-04-20 20:12:41.459677 : nsbasic_brc:2F 2A 20 74 65 73 74 63  |/*.testc|
  • トレース・ファイルの中身を確認する。
[oracle@localhost trace]$ grep -i tcp orcl_ora_3601.trc
2013-04-20 20:12:36.959360 : nsinh_hoff:ADR="(ADDRESS=(PROTOCOL=tcp)(DEV=14)(HOST=192.168.56.101)(PORT=1521))"
2013-04-20 20:12:36.959715 : nsc2addr:(ADDRESS=(PROTOCOL=tcp)(DEV=14)(HOST=192.168.56.101)(PORT=1521))
2013-04-20 20:12:36.966778 : nttcon:NT layer TCP/IP connection has been established.
2013-04-20 20:12:36.966984 : nttcon:set TCP_NODELAY on 14
2013-04-20 20:12:37.002025 : nsprecv:3D 74 63 70 29 28 48 4F  |=tcp)(HO|
2013-04-20 20:12:37.100779 : nsgetclientaddress:Client address: "(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.56.1)(PORT=1849))"
[oracle@localhost trace]$ grep -i tcp orcl_ora_3603.trc
2013-04-20 20:12:40.797698 : nsinh_hoff:ADR="(ADDRESS=(PROTOCOL=tcp)(DEV=14)(HOST=192.168.56.101)(PORT=1521))"
2013-04-20 20:12:40.798505 : nsc2addr:(ADDRESS=(PROTOCOL=tcp)(DEV=14)(HOST=192.168.56.101)(PORT=1521))
2013-04-20 20:12:40.806009 : nttcon:NT layer TCP/IP connection has been established.
2013-04-20 20:12:40.806195 : nttcon:set TCP_NODELAY on 14
2013-04-20 20:12:40.841755 : nsprecv:3D 74 63 70 29 28 48 4F  |=tcp)(HO|
2013-04-20 20:12:40.941021 : nsgetclientaddress:Client address: "(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.56.1)(PORT=1851))"

テスト手順

exec_testcase1.bat
exec_testcase2.bat

テストに使ったファイル

  • set_env.bat
set JAVA_HOME=C:\Program Files\Java\jdk1.5.0_22
set PATH=%JAVA_HOME%\bin;%PATH%
  • build_testcase1.bat
call set_env.bat
%~d0
cd %~p0
set CLASSPATH=.;ojdbc5.jar
javac TestCase1.java
pause
  • build_testcase2.bat
call set_env.bat
%~d0
cd %~p0
set CLASSPATH=.;ojdbc5.jar
javac TestCase2.java
pause
  • exec_testcase1.bat
call set_env.bat
%~d0
cd %~p0
set CLASSPATH=.;ojdbc5.jar
java TestCase1
pause
  • exec_testcase2.bat
call set_env.bat
%~d0
cd %~p0
set CLASSPATH=.;ojdbc5.jar
java TestCase2
pause
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class TestCase1 {
	public static void main(String args[]) {
		Connection conn = null;
		Statement stmt = null;
		ResultSet resultSet = null;
		try {
			Class.forName ("oracle.jdbc.driver.OracleDriver");
			conn = DriverManager.getConnection("jdbc:oracle:thin:@192.168.56.101:1521:orcl","system","manager");
			stmt = conn.createStatement();
			resultSet = stmt.executeQuery("select /* testcase1 */ sys_context('USERENV','INSTANCE_NAME'), sys_context('USERENV','SERVER_HOST') from dual");
			for(;resultSet.next();) {
				System.out.println(resultSet.getString(1));
				System.out.println(resultSet.getString(2));
			}
			try {
				if (resultSet != null) {
					resultSet.close();
				}
			} catch (SQLException e){
				e.printStackTrace();
			}
			try {
				if (stmt != null) {
					stmt.close();
				}
			} catch (SQLException e){
				e.printStackTrace();
			}
		} catch (SQLException e) {
			System.out.println("Error code: " + e.getErrorCode());
			System.out.println("SQL state: " + e.getSQLState());
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} finally {
			try {
				if (resultSet != null) {
					resultSet.close();
				}
			} catch (SQLException e){
				e.printStackTrace();
			}
			try {
				if (stmt != null) {
					stmt.close();
				}
			} catch (SQLException e){
				e.printStackTrace();
			}
			try {
				if (conn != null) {
					conn.close();
				}
			} catch (SQLException e){
				e.printStackTrace();
			}
		}
	}
}
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

public class TestCase2 {
	public static void main(String args[]) {
		Connection conn = null;
		Statement stmt = null;
		ResultSet resultSet = null;
		try {
			Class.forName ("oracle.jdbc.driver.OracleDriver");
			java.util.Properties info = new java.util.Properties();
			info.setProperty("user", "system");
			info.setProperty("password", "manager");
			info.setProperty("TCP.NODELAY", "YES");
			conn = DriverManager.getConnection("jdbc:oracle:thin:@192.168.56.101:1521:ORCL",info);
			stmt = conn.createStatement();
			resultSet = stmt.executeQuery("select /* testcase2 */ sys_context('USERENV','INSTANCE_NAME'), sys_context('USERENV','SERVER_HOST') from dual");
			for(;resultSet.next();) {
				System.out.println(resultSet.getString(1));
				System.out.println(resultSet.getString(2));
			}
			try {
				if (resultSet != null) {
					resultSet.close();
				}
			} catch (SQLException e){
				e.printStackTrace();
			}
			try {
				if (stmt != null) {
					stmt.close();
				}
			} catch (SQLException e){
				e.printStackTrace();
			}
		} catch (SQLException e) {
			System.out.println("Error code: " + e.getErrorCode());
			System.out.println("SQL state: " + e.getSQLState());
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} finally {
			try {
				if (resultSet != null) {
					resultSet.close();
				}
			} catch (SQLException e){
				e.printStackTrace();
			}
			try {
				if (stmt != null) {
					stmt.close();
				}
			} catch (SQLException e){
				e.printStackTrace();
			}
			try {
				if (conn != null) {
					conn.close();
				}
			} catch (SQLException e){
				e.printStackTrace();
			}
		}
	}
}

おまけ(ltrace でライブラリコールのトレースを取得する)

[root@localhost ~]# ltrace -tf -p 13079 -o ltrace.log
[root@localhost ~]# grep -C 2 -i setsockopt ltrace.log 
13090 21:04:07 __ctype_b_loc()                                                        = 0x147ed0
13090 21:04:07 free(0x11b6d080)                                                       = <void>
13090 21:04:07 setsockopt(14, 6, 1, 0xbfaec328, 4)                                    = 0
13090 21:04:07 malloc(4096)                                                           = 0x11b6d080
13090 21:04:07 vsnprintf("set TCP_NODELAY on 14\n", 4096, "set TCP_NODELAY on %d\n", 0xbfaec264) = 22
--
13090 21:04:08 write(8, "m}nttctl*0TgSY"1;\n", 18)                                    = 18
13090 21:04:08 free(0x11b750d0)                                                       = <void>
13090 21:04:08 setsockopt(14, 1, 9, 0xbfaebcbc, 4)                                    = 0
13090 21:04:08 malloc(4096)                                                           = 0x11b750d0
13090 21:04:08 vsnprintf("normal exit\n", 4096, "normal exit\n", 0xbfaebf80)          = 12
--
13090 21:04:13 write(8, "W}0TgmT"1;\n", 11)                                           = 11
13090 21:04:13 free(0x11b76110)                                                       = <void>
13090 21:04:13 setsockopt(14, 1, 21, 0xbfaf522c, 8)                                   = 0
13090 21:04:13 malloc(4096)                                                           = 0x11b76110
13090 21:04:13 vsnprintf("entry\n", 4096, "entry\n", 0xbfaf52a0)                      = 6
--
13090 21:04:13 write(8, "}0TgdP"1;\n", 10)                                            = 10
13090 21:04:13 free(0x11b76110)                                                       = <void>
13090 21:04:13 setsockopt(14, 1, 20, 0xbfaf522c, 8)                                   = 0
13090 21:04:13 malloc(4096)                                                           = 0x11b76110
13090 21:04:13 vsnprintf("entry\n", 4096, "entry\n", 0xbfaf5224)                      = 6
--
13090 21:04:13 write(8, "!nttdisc*0ThdS"1;\n", 18)                                    = 18
13090 21:04:13 free(0x11b76110)                                                       = <void>
13090 21:04:13 setsockopt(14, 1, 9, 0xbfaf520c, 4)                                    = 0
13090 21:04:13 close(14)                                                              = 0
13090 21:04:13 malloc(4096)                                                           = 0x11b76110
--
13097 21:04:19 __ctype_b_loc()                                                        = 0x633690
13097 21:04:19 free(0x1241a080)                                                       = <void>
13097 21:04:19 setsockopt(14, 6, 1, 0xbf990628, 4)                                    = 0
13097 21:04:19 malloc(4096)                                                           = 0x1241a080
13097 21:04:19 vsnprintf("set TCP_NODELAY on 14\n", 4096, "set TCP_NODELAY on %d\n", 0xbf990564) = 22
--
13097 21:04:20 write(8, "m}nttctl*0TgEW"1;\n", 18)                                    = 18
13097 21:04:20 free(0x124220d0)                                                       = <void>
13097 21:04:20 setsockopt(14, 1, 9, 0xbf98ffbc, 4)                                    = 0
13097 21:04:20 malloc(4096)                                                           = 0x124220d0
13097 21:04:20 vsnprintf("normal exit\n", 4096, "normal exit\n", 0xbf990280)          = 12
--
13097 21:04:25 write(8, "W}0Tg4U"8;\n", 11)                                           = 11
13097 21:04:25 free(0x12423110)                                                       = <void>
13097 21:04:25 setsockopt(14, 1, 21, 0xbf99952c, 8)                                   = 0
13097 21:04:25 malloc(4096)                                                           = 0x12423110
13097 21:04:25 vsnprintf("entry\n", 4096, "entry\n", 0xbf9995a0)                      = 6
--
13097 21:04:25 write(8, "}0TgUT"8;\n", 10)                                            = 10
13097 21:04:25 free(0x12423110)                                                       = <void>
13097 21:04:25 setsockopt(14, 1, 20, 0xbf99952c, 8)                                   = 0
13097 21:04:25 malloc(4096)                                                           = 0x12423110
13097 21:04:25 vsnprintf("entry\n", 4096, "entry\n", 0xbf999524)                      = 6
--
13097 21:04:25 write(8, "!nttdisc*0ThAR"1;\n", 18)                                    = 18
13097 21:04:25 free(0x12423110)                                                       = <void>
13097 21:04:25 setsockopt(14, 1, 9, 0xbf99950c, 4)                                    = 0
13097 21:04:25 close(14)                                                              = 0
13097 21:04:25 malloc(4096)                                                           = 0

参考

2013-03-23

Thunderbirdでimapでサーバサイドで振り分けルールを設定している場合にフォルダを選択しないと受信されない

Thunderbird 10.0.4 でメールサーバ (beehive) が imapサーバサイドで振り分けルールを設定している場合に、フォルダを選択しないとメールが受信されないのが不便だったのでちょっと調べてみた。mail.server.default.check_all_folders_for_new を true に設定するとよい。


設定方法


参考情報

以下のの情報が参考になった。

「受信」アイコンをクリックしても変わらず。フォルダをクリックしないと新規メールは現れないようです。

どのフォルダ(ラベル)にメールが来るかはわかりませんから、これでは本当に不便です。

(中略)

ツール>オプション>詳細>一般>高度な設定>設定エディタ

設定名"mail.check_all_imap_folders_for_new"を見つけて

ダブルクリックすれば"false"と"true"が切り替えられます。(初期値"false")

Thunderbird 上で imap で同期したアカウントの読み込みが遅い | E-MailのQ&A【OKWave】

2012-12-08

パイプライン表関数

テーブル・ファンクションは、行のコレクション(ネストした表またはVARRAY)を戻すユーザー定義のPL/SQLファンクションです。SELECT文のTABLE句の内部でテーブル・ファンクションを起動することで、データベース表のようにこのコレクションから要素を選択できます。次に例を示します。

SELECT * FROM TABLE(table_function_name(parameter_list))

(中略)

テーブル・ファンクションの実行をパラレル化でき、戻された行を中間的なステージングなしで次のプロセスに直接送ることができます。テーブル・ファンクションから戻されたコレクションに含まれる行を、パイプライン化することもできます。つまり、テーブル・ファンクションの入力の処理がすべて完了した後にバッチで戻すかわりに、生成されるたびに反復的に戻すことができます。

(中略)

スタンドアロン・ファンクションでは、CREATE FUNCTION文にPIPELINEDオプションを指定します(構文は、「CREATE FUNCTION文」を参照してください)。パッケージ・ファンクションでは、ファンクション宣言とファンクション定義の両方にPIPELINEDオプションを指定します(構文は、「ファンクションの宣言および定義」を参照してください)。

PL/SQLの最適化とチューニング

非パイプライン・テーブル・ファンクションの場合、問合せで1つの結果行が戻されるには、その前にテーブル・ファンクションから戻されるコレクション全体が構成され、サーバーに戻される必要があります。パイプライン化により、行が生成されるたびに反復的に戻すことができます。また、これにより、オブジェクト・キャッシュではコレクション全体をマテリアライズする必要がないため、テーブル・ファンクションに必要なメモリーも減少します。

(中略)

テーブル・ファンクションでのみ使用し、このファンクションがパイプラインであることを指定します。パイプライン・テーブル・ファンクションは、行を処理した直後に起動元に行を戻し、行の処理を継続します。起動元に(制御を戻さずに)行を戻すために、このファンクションでは「PIPE ROW文」を使用します。

ファンクションの宣言および定義

ライン生産方式などパイプライン的なものは様々なところに存在する。自動車の組み立てを考えてみよう。流れ作業の一工程として、エンジンのシャーシへの設置、フードの設置、車輪の設置があり、この順番で実施されるとする。ラインの各工程には、1台の組み立て中の自動車だけがある。エンジンを設置し終えた自動車は、次にフードの設置工程に移され、エンジン設置用の機械設備は次の自動車に取り掛かることができる。最初の自動車はさらに車輪設置工程に進み、2台目の自動車はフード設置工程に進み、3台目の自動車がエンジン設置工程に進んでくる。エンジン設置に20分かかり、フード設置に5分、車輪設置に10分かかるとすると、一度に1台ずつ組み立てると3台組み立てるのに105分かかる。しかし、ライン生産方式では75分で3台の組み立てが完了する。その後も20分間隔で自動車が組み立てられていく。

パイプライン処理 - Wikipedia

まとめ*1

  • 表関数は表をSELECTしたときのように複数行を返す関数。
  • 結果が全部揃うまで待つのではなくできた行から順次帰す表関数がパイプライン表関数。
  • 仕組みは自動車組立工場のライン生産方式と同じ。
  • 1人の職人が一から自動車を組立ていた時代もあるが、自動車組立工場では100台全てのシャーシにエンジンを設置し終えてからタイヤを取り付けるのではなく、できたものが次の工程に流して各工程の組立を並列で行っているため、同じ時間でたくさんの自動車を作ることができる。
  • パイプライン表関数のメリットとして全部結果ができてから返すのではなく、できた行から順次返すのでデータを溜めておくメモリが少なくてすむといった点がある。

関連

  • Oracle Database PL/SQL言語リファレンス 11gリリース2(11.2) B56260-04
  • KROWN#42793

*1:正確さよりわかりやすさ重視

2012-11-23

LINUXカーネルHACKS

図書館で借りてきた本。買いたい本だが、たしか会社にあったので必要な時は会社で借りよう。

返却する前に crash コマンドで気になったところをメモしておく。


P.401

crash コマンドはカーネルイメージの解析が可能なデバッグツールです。gdb コマンドをベースに設計されており、カーネル内部の各種情報を参照するために多くのコマンドを駆使して、対話的に作業を進めることができます。


P.406

btコマンド

...

-f オプションはフレーム内のスタックデータをすべて表示します。このオプションは関数への引数を確認するときに便利です。-l オプションはファイル名と行数を表示します。


P.409

kemem コマンド

カーネルのメモリ使用量に関する情報を表示します。-s オプションはスラブキャッシュの情報を表示します。/proc/slabinfo と同等の情報になります。

...

-i オプションは、メモリ全体の利用状況を表示します。

...

-p オプションでメモリマップを表示します。


P.413

runq コマンドはプロセススケジューラのランキューに繋がっているプロセス(実行中プロセス)を表示します。


runq コマンドだけ試してみた。

crash> runq
CPU 0 RUNQUEUE: c170e780
  CURRENT: PID: 13000  TASK: e8c48aa0  COMMAND: "crash"
  ACTIVE PRIO_ARRAY: c170ec3c
     [115] PID: 13000  TASK: e8c48aa0  COMMAND: "crash"
           PID: 12932  TASK: f7384000  COMMAND: "sshd"
     [117] PID: 13113  TASK: cfccf000  COMMAND: "less"
     [125] PID: 13108  TASK: e8c48550  COMMAND: "perl"
           PID: 13107  TASK: cfccf550  COMMAND: "perl"
  EXPIRED PRIO_ARRAY: c170e7c4
     [no tasks queued]

2012-11-06

特定の拡張子のファイルの合計サイズを調べる

man で調べてみると、

$ man du

...

       -c, --total
              produce a grand total

-c というオプションがあるらしいので試してみると、

$ du -c *.txt
224     1.txt
20      2.txt
244     total

でた。

xargs で標準入力がない場合は何もしない

F本さんに

オハヨウゴザイマス

コマンド結果 | xargsで、

コマンド結果がない場合、xargsにつながないようにするのって

どうするんでしたっけ?

と聞かれたので調べてみた。

-r 標準入力に空白しか含まれていない場合は、指定したコマンドを実行しない。 通常では、入力が全くない場合でも、コマンドが一回は実行されるのだ。 このオプションは GNU の拡張である。

Man page of XARGS

-r オプションでできるみたいなので試してみた。

$ echo|xargs echo foo
foo
$ echo|xargs -r echo foo

できますた。


追記:

GNU xargs使うときは -0r デフォですね。OSXのだと -r ないけど。。。

Twitter / yoshikaw: GNU xargs使うときは -0r ...

r は知りませんですた。すんまそん。