複数のセッションから実行される postgresql 関数に問題があります。関数foo
は、まったく同時に複数のセッションで作成されます。これにより、ログイン機能が同時に実行されます。
login 関数 (以下を参照) 内にはIF token does not exists THEN
、まったく同時に実行される if ステートメントがあります。もちろん、トークンがまだ作成されていないため、すべての関数で false になります。
これは私が望む動作ではありません。login
関数を「スレッドセーフ」にする方法はありますか。Javaで同期したような?
擬似関数:
CREATE OR REPLACE FUNCTION foo() RETURNS VARCHAR AS
$body$
BEGIN
token = login();
result = doStuffWithTheLogin(token);
IF result = LoginFailed THEN
token = login(true);
RETURN 'RETRY';
END IF;
END;
$body$
LANGUAGE 'plpgsql'
SECURITY DEFINER;
ログイン機能:
CREATE OR REPLACE FUNCTION login(forceReload BOOLEAN) RETURNS VARCHAR AS
$body$
BEGIN
IF NOT forceReload THEN
token = getTokenFromStorage();
END IF;
IF token does not exists THEN
token = createNewToken();
saveTokenToStorage(token);
END IF;
RETURN token;
END;
$body$
LANGUAGE 'plpgsql'
SECURITY DEFINER;
テーブルロックを試してみました。しかし、それは本当に仕事をしませんでした。関数が完了するまでに約 2 ~ 3 秒かかりますlogin
。100 個の foo タスクがある場合、テーブルは長時間ロックされます。