dbts2013 特濃jpoug log_file_sync
DESCRIPTION
TRANSCRIPT
Copyright © 2013 Insight Technology, Inc. All Rights Reserved.
Insight Technology, Inc.JPOUG (Japan Oracle User Group)
新久保 浩二 (@kouji_s_0808)
OLTPにつける薬はあるのか? - log file sync の進化と謎 -
2Copyright © 2013 Insight Technology, Inc. All Rights Reserved.
Who am I ?
1. データベース マニアック担当
2. Oracle ACE
3. JPOUG(Japan Oracle User Group)
(http://www.jpoug.org)
本資料に使用されている社名、ロゴ、製品、サービス名およびブランド名は、該当する各社の登録商標または商標です。本資料の一部あるいは全体について、許可なく複製および転載することを禁じます。
本資料の内容に関して、不適当な表現や検証が足りない部分もありますがご容赦ください。
3Copyright © 2013 Insight Technology, Inc. All Rights Reserved.
COMMIT
用途
COMMIT文を使用すると、現行のトランザクションを終了し、トランザクションで
実行したすべての変更を確定できます。トランザクションとは、Oracle Databaseが
1つの単位として扱う一連のSQL文です。
また、この文によって、トランザクション内のセーブポイントがすべて消去され、
トランザクション・ロックが解除されます。
Database SQL言語リファレンスより
こ み っ と
4Copyright © 2013 Insight Technology, Inc. All Rights Reserved.
本日の試み
本日は、日頃皆さんが何気なく実行するcommitを肴に、
「commitする人の気持ち」 と
「commitされる人の気持ち」
を堪能しようという試みです。
- commitの裏舞台では、どんな事がくりひろげられてるの?
- Oracleリリースが進んで、 commit関連の何かが変わったの?- 11gでは?
- 12cでは?
- 深まる謎?
とか (ちなみに、本資料の環境は主にLinux上でのお話です。)
8Copyright © 2013 Insight Technology, Inc. All Rights Reserved.
$ ps -ef | grep sqlplus | grep –v greporacle 31699 31645 0 07:55 pts/1 00:00:00 sqlplus as sysdba
$ pstree -alp 31699sqlplus,31699 ¥040 as sysdba│└─ oracle,32567 (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))
$ ps -ef | grep lgwr | grep –v greporacle 31595 1 0 Nov02 ? 00:22:16 ora_lgwr_oracle11g
フォアグランド
SHADOWプロセス(commitする人)
LGWR(commitされる人)
今日の大事な点 その1 (プロセスの関係)
今日は、この人たちのsystem callを追いかけます。(latch等は追いかけません)
9Copyright © 2013 Insight Technology, Inc. All Rights Reserved.
SEMCTL(2) Linux Programmer’s Manual SEMCTL(2)
名前semctl - セマフォの制御操作を行なう
書式#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>
int semctl(int semid, int semnum, int cmd, ...);
説明semctl() は、 semid で指定されたセマフォ集合 (semaphore set) またはセマフォ集合のsemnun 番目のセマフォに対して、 cmd で指定された制御操作を行なう (集合内のセマフ ォの番号は 0 から始まる)。
この関数は、 cmd の値に依存して、3 個または 4 個の引き数を持つ。引き数が 4 個の場合、第 4 引き数の型は union semun である。呼び出し元プログラムは、この共用体 (union)を以下のように定義しなければならない。
union semun {int val; /* SETVAL の値 */struct semid_ds *buf; /* IPC_STAT, IPC_SET 用のバッファ */unsigned short *array; /* GETALL, SETALL 用の配列 */struct seminfo *__buf; /* IPC_INFO 用のバッファ
(Linux 固有) */};
今日の大事な点 その2 (セマフォ)
SEMOP(2) Linux Programmer’s Manual SEMOP(2)
名前semop, semtimedop - セマフォの操作
書式#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>
int semop(int semid, struct sembuf *sops, unsigned nsops);
int semtimedop(int semid, struct sembuf *sops, unsigned nsops,struct timespec *timeout);
glibc 向けの機能検査マクロの要件 (feature_test_macros(7) 参照):
semtimedop(): _GNU_SOURCE
説明セマフォ集合 (semaphore set) のメンバーの各セマフォは以下の関連情報を持っている:
unsigned short semval; /* セマフォ値 */unsigned short semzcnt; /* ゼロを待つプロセス数 */unsigned short semncnt; /* 増加を待つプロセス数 */pid_t sempid; /* 最後に操作を行なったプロセス */
semop() は semid で指定されたセマフォ集合の選択されたセマフォに対して操作を行う。
semctl(2)他のプロセスを起こす
semtimedop(2)他のプロセスに起こされ
るまで寝る
10Copyright © 2013 Insight Technology, Inc. All Rights Reserved.
一般的なcommit (11.2.0.4)
皆さんご存知のcommitの動作SHADOW PROCESS LGWR ------------------------------------------------------------------------------ ------------------------------------------------------------------15:56:52.451519 semtimedop(1802252, {{18, -1, 0}}, 1, {3, 0}) = -1 EAGAIN15:56:55.452866 semtimedop(1802252, {{18, -1, 0}}, 1, {3, 0}) = -1 EAGAIN15:56:58.454356 semtimedop(1802252, {{18, -1, 0}}, 1, {3, 0}) = 15:57:01.125824 update !15:57:01.129724 update complete15:57:01.181562 commit !15:57:01.184351 semctl(1802252, 18, SETVAL, 0x1) = 015:57:01.184939 io_submit(140400303636480, 2, {{0x7fb17c6a1480, 0, 1, 0, 267}, …}) = 215:57:01.185218 semtimedop(1802252, {{34, -1, 0}}, 1, {0, 100000000}) = 15:57:01.185558 io_getevents(140400303636480, 2, 128, {{0x7fb17c6a1480,…,{0,0}) = 215:57:01.185729 semctl(1802252, 34, SETVAL, 0x1) = 015:57:01.186277 semtimedop(1802252, {{18, -1, 0}}, 1, {0, 270000000}) = -1 EAGAIN15:57:01.186385 commit complete15:57:01.457908 semtimedop(1802252, {{18, -1, 0}}, 1, {3, 0} =
Shadow process
LGWR process
2789μ秒
588 μ秒 619 μ秒 171 μ秒
656 μ秒commit semctl semtimedop
commit complete
io_submit io_getevents semctl
semtimedop
log file sync
log file parallel write
多分、log file sync は shadowプロセスがsemtimedop(2)で眠ってから、LGWRに起こされて、commit完了を内部的に確認
できるまで
11Copyright © 2013 Insight Technology, Inc. All Rights Reserved.
深まる謎 その1
プロセスの復帰に関して、OSのプロセス・スケジューラーの影響はあるのか?
Shadow process
LGWR process
2789μ秒
588 μ秒 619 μ秒 171 μ秒
656 μ秒commit semctl semtimedop
commit complete
io_submit io_getevents semctl
semtimedop
log file sync
log file parallel write
もし、影響があるとしたら、Linuxのタイマー割り込み分解性能ってHZ依存Tickで1msとか4msとか10msとかじゃなかった?
そうなると、環境によっては、残念なこともあるかもしれない?
12Copyright © 2013 Insight Technology, Inc. All Rights Reserved.
深まる謎 その1 の考察
まず、RHEL5.6 (2.6.18-238.el5) と OEL6.4(2.6.39-400.209.1.el6uek.x86_64)で、nanosleep(2)で10回、1μ秒スリープしてみてOSのプロセス・スケジューラーによる遅延を確認してみる。
最近のOS(検証環境はOracle Linux 6.4 - UEK) だとTicklessカーネル&高精度タイマーになっていて、昔みたいにHZ依存のTickで世界が縛られることはなくなっているよう。
これだと、OSのバージョンで、相当OLTP性能へ影響が出てしまうはずだが、本当なのか?
56 55 55 55 54 55 54 55 61
1971 2005 1994 2007 1986 2000 21441860
1993
0
1,000
2,000
3,000
#1 #2 #3 #4 #5 #6 #7 #8 #9
μ秒
OS別割り込み分解性能
2.6.39-400.209.1.el6uek.x86_64 2.6.18.238.el5-x86_64
13Copyright © 2013 Insight Technology, Inc. All Rights Reserved.
深まる謎 その1 の考察
ということで、簡単なセマフォのサンプルで試してみた。
正確にカーネルのソースは見てないですが、nanosleep(2)の場合はOSのプロセス・スケジューラーがタスク状態を変更して、セマフォ関連は、OSのプロセス・スケジューラーに非依存で実装されている模様(ここ、大事)
61
93 8960
8166 57
106
6046 58
45
185
53 45 48
131
45
0
100
200
#1 #2 #3 #4 #5 #6 #7 #8 #9
μ秒
セマフォでのWakeup時間の実測値
2.6.39-400.209.1.el6uek.x86_64 2.6.18.238.el5-x86_64
なので、セマフォを使ってcommitの状態のやり取りを行っている限り、OSのプロセス・スケジューラーの遅延は、そんなに気にならないくらい高速。(でも遅延 - log file sync - は無くならない)
15Copyright © 2013 Insight Technology, Inc. All Rights Reserved.
(余談) commitする人にも事情はあるので
皆さんご存知のcommitのモードは大きく4つ
commitのモードは[IMMEDIATE] と BATCHcommitの待機モードは[WAIT] と NOWAIT
初期パラメーターで指定するなら10gの頃は
COMMIT_WRITE=“IMMEDIATE,WAIT” とか11g以降は
COMMIT_LOGGING=IMMEDIATECOMMIT_WAIT=WAIT とか
SQL単位で指定するならcommit write immediate wait; とか
皆さんご存知のPL/SQLのcommitのデフォルトモードはBATCH NOWAIT
❝ データベース初期化パラメータCOMMIT_LOGGINGおよびCOMMIT_WAITが設定されていない場合、非分散トランザクションに対するPL/SQLのデフォルトのコミット動作はBATCH NOWAITです。❞
PL/SQL言語リファレンス より
16Copyright © 2013 Insight Technology, Inc. All Rights Reserved.
(余談) commitモードによる違い (11.2.0.4)
% time seconds usec/call calls errors syscall
7.50 0.000472 5 100 0 semtimedop
0.37 0.000023 0 100 0 semctl
PL/SQL immediate wait
PL/SQL batch wait
% time seconds usec/call calls errors syscall
0.00 0.00000 0 100 0 semtimedop
0.00 0.00000 0 100 0 semctl
PL/SQL で commit のモードを変えながら、100回update + commitを実行
17
% time seconds usec/call calls errors syscall
0.39 0.000023 0 100 0 semctl
0.00 0.000000 0 1 0 semtimedop
% time seconds usec/call calls errors syscall
0.00 0.000000 0 2 0 semctl
0.00 0.000000 0 1 0 semtimedop
% time Seconds usec/call calls errors syscall
0.00 0.000000 0 100 0 semctl
0.00 0.000000 0 1 0 semtimedop
Copyright © 2013 Insight Technology, Inc. All Rights Reserved.
(余談) commitモードによる違い (11.2.0.4)
PL/SQL immediate nowait
PL/SQL batch nowait
PL/SQL commit (DEFAULT)
このケースだとPL/SQLで実行しているので(多分)PL/SQLブロックの抜ける際に、semctl(2)でLGWRを起こ
して、semtimedop(2)でlog bufferのフラッシュ完了を待っている。
普通のSQLだと、semtimedop(2)は実行されない。つまり、REDOログへの書き込みの正常性を全くチェック
しませんので、ご注意を!
さらに、semtimedop(2)で待たないので当然log file syncも(ほぼ)ない
です。
18Copyright © 2013 Insight Technology, Inc. All Rights Reserved.
(余談) commitモードでの速度比較
ご参考までに
76.921 75.878
12.395 10.832 11.739
0
10
20
30
40
50
60
70
80
90
PL/SQL IMMEDIATE
WAIT
PL/SQL BATCH WAIT PL/SQL IMMEDIATE
NOWAIT
PL/SQL BATCH NOWAIT PL/SQL COMMIT
(DEFAULT)
Ela
psed
Tim
e(s
ec)
100,000 commits per every insert
commit mode comparison (11.2.0.4)
20Copyright © 2013 Insight Technology, Inc. All Rights Reserved.
新種のcommit発見! (11.2.0.4)
(少なくとも私は知らなかった)新種のcommitが出てきました!SHADOW PROCESS LGWR ------------------------------------------------------------------------------ ------------------------------------------------------------------12:04:11.936399 semtimedop(1802252, {{18, -1, 0}}, 1, {3, 0}) = -1 EAGAIN12:04:14.940066 semtimedop(1802252, {{18, -1, 0}}, 1, {3, 0}) = 12:04:16.385834 update !12:04:16.388814 update complete12:04:16.388954 commit !12:04:16.601262 semctl(1802252, 18, SETVAL, 0x1) = 012:04:16.601762 nanosleep({0, 466000}, 0x7fff24c2dc80) = 012:04:16.602330 io_submit(140400303636480, 2, {{…}}) = 212:04:16.602380 nanosleep({0, 466000}, 0x7fff24c2dc80) = 012:04:16.602995 nanosleep({0, 466000}, 0x7fff24c2dc80) = 012:04:16.603163 io_getevents(140400303636480, 2, 128,…,{0,0}) = 212:04:16.603724 semtimedop(1802252, {{18, -1, 0}}, 1, {1, 340000000}) = -1 EAGAIN12:04:16.604007 commit complete12:04:17.945345 semtimedop(1802252, {{18, -1, 0}}, 1, {3, 0}) = -1 EAGAIN
Shadow process
LGWR process
312.308ミリ秒
1068 μ秒
commit
log file sync
log file parallel write
semctl nanosleepnanosleepnanosleepcommit
complete
io_submit io_getevents semtimedop
500 μ秒 618 μ秒 615 μ秒 1012 μ秒
833 μ秒 561 μ秒
semtimedop(2)で眠るかわりに
nanosleep(2)で眠っている
semctl(2)で他のプロセスを起こす。ということはしない
21Copyright © 2013 Insight Technology, Inc. All Rights Reserved.
post/wait と post/polling (11.2.0.x)
11gR2から初期化パラメーター “_use_adaptive_log_file_sync” デフォルトFALSEが登場しました。
あまり詳細ではないですが、以下に情報があります。
MOS 1541136.1 Waits for "log file sync" with Adaptive Polling vs Post/Wait Choice Enabled
ちなみに11.2.0.3からは、デフォルト TRUEになってました。
パラメーターの名前から分かるとおり、log file sync (つまり、shadow プロセスが、LGWRが行う、REDOログへの書き込み完了通知を待っている) に関して、
- post/wait (セマフォを使ってLGWRがshadowプロセスにREDOログ書き込み完了を通知)- post/polling (shadowプロセスがsleepにより自身でREDOログ書き込み完了を確認)
の2つの方式を動的に変更するといった機能です。
22Copyright © 2013 Insight Technology, Inc. All Rights Reserved.
深まる謎 その2
Shadow process
LGWR process
2789μ秒
588 μ秒 619 μ秒 171 μ秒
656 μ秒commit semctl semtimedop
commit complete
io_submit io_getevents semctl
semtimedop
log file sync
Shadow process
LGWR process
312.308ミリ秒
1068 μ秒
commit
log file sync
semctl nanosleepnanosleepnanosleepcommit
complete
io_submit io_getevents semtimedop
500 μ秒 618 μ秒 615 μ秒 1012 μ秒
833 μ秒 561 μ秒
で、誰が、どんな理由で、お得なんでしょうか?
post/wait
post/polling
23Copyright © 2013 Insight Technology, Inc. All Rights Reserved.
深まる謎 その2 の考察
post/poll
大量のセッションが大量のcommitを同時多発的に
実行した際、post/wait方式であれば、LGWRは全てのcommit要求元にsemctl(2)で通
知する必要がある。
このsemctl(2)による通知が忙しくて、本来の仕事のonline REDOログへフラッシュが怠けがちなっているシステムでは、post/pollingによるsemctl(2)からの解放は有効かもしれない。
LGWRは喜ぶ
従来のpost/waitはLGWRから通知されていたので、可能な限り即時にcommit完了通知を受け
取ることができた。
しかし、post/pollingではnanosleep(2)(このテスト時は466μ秒だったが、実際は動的に決定されると思う)でスリープするので、無駄に寝てしまって、 commitのレイテンシーが悪化する可能性があると思われる。
log file syncは増える可能性もある?
25Copyright © 2013 Insight Technology, Inc. All Rights Reserved.
ん!?なパターンも出てきた (12.1.0.1)
LGWRは新種のLG00(LGWR Worker)へ“左から右に受け流している”SHADOW PROCESS LGWR LG00----------------------------------------------- ---------------------------------------------------- ----------------------------------------------------18:29:18.575401 semtimedop(622604, {{19,…}}, 1, {3, 0}) = -1 EAGAIN18:29:21.577337 semtimedop(622604, {{19,…}}, 1, {3, 0}) = -1 EAGAIN18:29:21.963171 semtimedop(622604, {{21,…}}, 1, {3,0}) = -1 EAGAIN18:29:24.579259 semtimedop(622604, {{19,…}}, 1, {3, 0}) =18:29:24.964188 semtimedop(622604, {{21,…}}, 1, {3,0}) =18:29:25.658472 update !18:29:25.661777 update complete18:29:25.662136 commit !18:29:25.677012 semctl(622604, 19, SETVAL,…) = 018:29:25.677411 semctl(622604, 21, SETVAL, 0x7fff00000001) = 018:29:25.677655 semtimedop(622604, {{19,…}}, 1, {1, 910000000}) =18:29:25.677772 io_submit(139749499707392, 2, {{…}}) = 218:29:25.677838 semtimedop(622604, {{33,…}},…) =18:29:25.678392 io_getevents(139749499707392, 2, 128,…,{0,0}) = 218:29:25.678967 semctl(622604, 33, SETVAL, 0x7fff00000001) = 018:29:25.679130 semctl(622604, 19, SETVAL, 0x7fff00000001) = 018:29:25.679370 semtimedop(622604, {{19,…}},…) =18:29:25.679676 commit complete18:29:27.580963 semtimedop(622604, {{19,…}}, 1, {3, 0}) = -1 EAGAIN
26Copyright © 2013 Insight Technology, Inc. All Rights Reserved.
新種のプロセス LGnn (12.1.0.1)
12cR1から初期化パラメーター “_use_single_log_writer” デフォルトADAPTIVEが登場している。どうやら、Scalable Log Writerとも呼ばれるらしい。
詳細不明ですが、新種のプロセスLGnn(Log Writer Workerプロセス)がデフォルトで2つ起動され、状況により、複数のWorkerプロセスに、I/Oを任せることで、REDOログへの書き込みスループットを向上させようとしていると考えられる。
ちなみに、LGnnのプロセス数は”_max_outstanding_log_writes”で制御されている模様
“_use_single_log_writer”の設定として- TRUE 常にシングル(LGWR)がREDOログへの書き込みを担う。従来の動作- FALSE 常に一旦LGWRが要求を受けて、LGnnがREDOログへ書き込む。- ADAPTIVE きっと、両者を動的に切り替える
27Copyright © 2013 Insight Technology, Inc. All Rights Reserved.
深まる謎 その3
正直、ADAPTIVE状態では、なかなか、Workerプロセスを使うモードに移行してくれなかった。さらに、強制的にWorkerプロセスを使うモード(先ほどのスライドの例)だと、プロセス間通信による遅延が増え、全体的なcommitレスポンスは悪化していた。(そういうパターンもあった)
Scalable Log Writerの力はこんなものではないはずなので、今後、要検証。
Shadow process
LGWR process
log file syncScalable Log Writer
LG00 process
commit semctl semtimedopcommit
complete
semctl semtimedopsemtimedop
semctl semctlio_submit io_getevents
28Copyright © 2013 Insight Technology, Inc. All Rights Reserved.
と言うことで
なじみ深いcommitという動作一つでも、奥は深い。
データベースでは、非常にベーシックなアーキテクチャでも、時代と共に変化していきている。
ただ、その機能やアーキテクチャの変更が、現在のシステムに有効かどうかは、現時点では、ちゃんと見極める必要がある。 (過度に憶病になる必要はないと思いますが)
ただ、流行りのAdaptiveといった説明にならない説明は個人的には嫌いです。
なので、常識の範囲で、中身を見てみると、その機能の気持ちも分かるようになるし、得意、不得意な点も見えてくるので、個人的にはおススメ。
(ただ、本番環境では絶対にやらないでくださいね。)
最後に、データベースのパフォーマンス問題は奥が深いので、一言で解決可能な魔法の薬は存在しません。現象を理解し、深く解析し、データベースやそのプロセスの気持ちになって考えてあげる事が大切です。
30Copyright © 2013 Insight Technology, Inc. All Rights Reserved.
#include <stdio.h>#include <stdlib.h>#include <time.h>#include <sys/time.h>#include <unistd.h>
int LOOP = 10;
int main (int argc, char **argv){
struct timeval tv[LOOP];struct timespec req;int i;
req.tv_sec = 0;req.tv_nsec = 1000; // 1us
for (i = 0; i < LOOP; i++) {nanosleep(&req, NULL);gettimeofday(tv + i, NULL);
}
for (i = 0; i < LOOP; i++)printf("%ld:%06ld¥n", (long)tv[i].tv_sec, (long)tv[i].tv_usec);
return 0;}
Appendix: tick_test.c
31Copyright © 2013 Insight Technology, Inc. All Rights Reserved.
#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>#include <stdio.h>
#define KEY (1492)
int main(){
int id;union semun {
int val;struct semid_ds *buf;ushort * array;
} argument;
argument.val = 0;id = semget(KEY, 1, 0666 | IPC_CREAT);
if(id < 0){
fprintf(stderr, "Unable to obtain semaphore.¥n");return 0;
}
if( semctl(id, 0, SETVAL, argument) < 0){
fprintf( stderr, "Cannot set semaphore value.¥n");}else{
fprintf(stderr, "Semaphore %d initialized.¥n", KEY);}
}
Appendix: seminit.c
32Copyright © 2013 Insight Technology, Inc. All Rights Reserved.
#include <stdio.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>
#define KEY (1492)
int main(){
int id;int retval;struct timeval tv;
id = semget(KEY, 1, 0666);if(id < 0){
fprintf(stderr, "Program cannot find semaphore, exiting.¥n");return 0;
}
printf("Program about to do a V-operation. ¥n");
gettimeofday(&tv, NULL);printf("%ld:%06ld¥n", (long)tv.tv_sec, (long)tv.tv_usec);retval = semctl(id, 0, SETVAL, 1);
if(retval == 0){
printf("Successful V-operation by program sem_wakeup.¥n");}else{
printf("sem_wait: V-operation did not succeed.¥n");perror("REASON");
}}
Appendix: sem_wakeup.c
33Copyright © 2013 Insight Technology, Inc. All Rights Reserved.
#include <stdio.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>#include <stdlib.h>#include <time.h>#include <sys/time.h>#include <unistd.h>
#define KEY (1492)
int main(){
int id;struct sembuf operations[1];int retval;struct timeval tv;struct timespec req;
req.tv_sec = 10;req.tv_nsec = 0;
id = semget(KEY, 1, 0666);if(id < 0){
fprintf(stderr, "Program cannot find semaphore, exiting.¥n");return 0;
}
printf("Program about to do a P-operation. ¥n");printf("Process id is %d¥n", getpid());
operations[0].sem_num = 0;operations[0].sem_op = -1;operations[0].sem_flg = 0;
Appendix: sem_wait.c
gettimeofday(&tv, NULL);printf("%ld:%06ld¥n", (long)tv.tv_sec, (long)tv.tv_usec);
retval = semtimedop(id, operations, 1, &req);
gettimeofday(&tv, NULL);printf("%ld:%06ld¥n", (long)tv.tv_sec, (long)tv.tv_usec);
if(retval == 0){
printf("Successful P-operation by program sem_wait.¥n");printf("Process id is %d¥n", getpid());
}else{
printf("sem_wait: P-operation did not succeed.¥n");}
}