[pgsql-jp: 31030] Re: TL8 AMD64で共有メモリに上限?
Tatsuo Ishii
t-ishii @ sra.co.jp
2003年 9月 10日 (水) 23:43:12 JST
石井です.フォローが遅くなりました.
> >失礼.見たいのは ipcs -l -sの結果でした.
> >
> ありゃ。今、マシンはバラしてあるんですが、あとで報告しましょうか?
今回の場合,そんなに本質的な情報ではないので,可能ならばで結構です.
> >明らかにTLD AMD64上のPostgreSQLは異常な動作をしていますね.32bitモード
> >でコンパイルしたPostgreSQLでも動作がおかしいということは,TLD AMD64に
> >問題があるような気がします.残念ながらここから先はデバッガでも使わない
> >とちょっとわからないですね.
> >--
>
> そうですか。デバッガでコードを追うようなことは、もう10数年やってないし、
> UNIX系OSの知識も乏しいのですが、ちょっとやってみたい気もします。
> 厚かましいですが、簡単に手ほどきして、いただけませんか?
> そんな、甘いもんじゃないですかね?
なぜ不具合が起きているかはすぐにわかると思いますが,対処法がわかるかど
うかはまた別問題です:-)それでもよければ,ということで...
まずソースコードをしらみつぶしに当るのは効率悪すぎるので,エラーメッセー
ジであたりをつけます.
cd postgresql-7.3.4/src/backend
find . -name '*.c' -print|xargs grep IpcSemaphoreCreate
./port/sysv_sema.c:76:static IpcSemaphoreId IpcSemaphoreCreate(int numSems);
./port/sysv_sema.c:116: fprintf(stderr, "IpcSemaphoreCreate: semget(key=%d, num=%d, 0%o) failed: %s\n",
./port/sysv_sema.c:218:IpcSemaphoreCreate(int numSems)
./port/sysv_sema.c:359: mySemaSets[numSemaSets] = IpcSemaphoreCreate(SEMAS_PER_SET);
./port/pg_sema.c:76:static IpcSemaphoreId IpcSemaphoreCreate(int numSems);
./port/pg_sema.c:116: fprintf(stderr, "IpcSemaphoreCreate: semget(key=%d, num=%d, 0%o) failed: %s\n",
./port/pg_sema.c:218:IpcSemaphoreCreate(int numSems)
./port/pg_sema.c:359: mySemaSets[numSemaSets] = IpcSemaphoreCreate(SEMAS_PER_SET);
怪しそうなのは ./port/sysv_sema.c:116: ではないかとあたりがつきます(ち
なみに,Linuxの場合,./port/pg_sema.cはpg_sema.cへのリンク).そのあた
りはstatic IpcSemaphoreId InternalIpcSemaphoreCreate(IpcSemaphoreKey
semKey, int numSems)なんですが,コードを見ると,単にsemget()しているだ
けです.semget()自体がおかしいと言うわけでもなさそうなので,その上位関
数へと探索の手を延します.すると,230行目あたりの
semId = InternalIpcSemaphoreCreate(nextSemaKey, numSems + 1);
が目につきます.InternalIpcSemaphoreCreateが1回呼ばれるとsemget()が1回
呼ばれるようなので,どうもなんらかの理由でInternalIpcSemaphoreCreateが
呼ばれすぎているのではないか,と考えます.さらにこれを呼び出している関
数は同じファイルの中の以下です.
PGSemaphoreCreate(PGSemaphore sema)
{
/* Can't do this in a backend, because static state is postmaster's */
Assert(!IsUnderPostmaster);
if (nextSemaNumber >= SEMAS_PER_SET)
{
/* Time to allocate another semaphore set */
if (numSemaSets >= maxSemaSets)
elog(PANIC, "PGSemaphoreCreate: too many semaphores created");
mySemaSets[numSemaSets] = IpcSemaphoreCreate(SEMAS_PER_SET);
numSemaSets++;
nextSemaNumber = 0;
}
/* Assign the next free semaphore in the current set */
sema->semId = mySemaSets[numSemaSets - 1];
sema->semNum = nextSemaNumber++;
/* Initialize it to count 1 */
IpcSemaphoreInitialize(sema->semId, sema->semNum, 1);
}
でも,これも関数呼び出しごとに1回セマフォをgetしているだけなので,更に
これを呼び出している関数を探すと,storage/lmgr/proc.cにInitProcGlobal
というのがあります.この中で,
for (i = 0; i < maxBackends; i++)
{
PGPROC *proc;
proc = (PGPROC *) ShmemAlloc(sizeof(PGPROC));
if (!proc)
elog(FATAL, "cannot create new proc: out of memory");
MemSet(proc, 0, sizeof(PGPROC));
PGSemaphoreCreate(&proc->sem);
proc->links.next = ProcGlobal->freeProcs;
ProcGlobal->freeProcs = MAKE_OFFSET(proc);
}
のようなことをやっています.ここでmaxBackendsは同時接続数
(max_connections)です.つまり,同時接続数分だけセマフォを取得している
わけです.どうもmaxBackendsよりも余計にこのループを回っているような気
がするのですが,とりあえずこのあたりを調べてみてはいかがでしょう?
--
Tatsuo Ishii
pgsql-jp メーリングリストの案内