2016-04-03 6 views
5

Phantomの読み取りを阻止するか、そうでなければPostgresのトランザクションで見つからない行をロックすることは可能ですか?接続2に、Postgresでファントムの読み込みを防ぐには?

CREATE TABLE weather (city varchar(80) PRIMARY KEY); 
BEGIN; 
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 
INSERT INTO weather VALUES ('a'); 

一方:

1接続の場合:たとえば、次のコマンドシーケンスを考慮

BEGIN; 
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 
SELECT * FROM weather WHERE city = 'a' FOR SHARE; 
INSERT INTO weather VALUES ('b'); 

をバック接続1:

COMMIT; 

そして再度接続2に戻る:

COMMIT; 
SELECT * FROM weather; 
-- Shows both rows 

行 'b'を作成するための前提条件が行 'a'がないために、接続2のトランザクションが成功することは不可能に思えます。 2番目のトランザクションが成功しないようにするにはどうすればよいですか?テーブル全体をロックせずにそれを行うの

+0

PostgreSQLバージョン? –

+0

psql(PostgreSQL)9.3.11 –

+1

シリアル化可能トランザクションは、その動作がトランザクションの*いくつかのシリアル順序と一致する限り成功する可能性がありますが、この順序付けは、トランザクションの開始またはコミットの順序とは関係ありません。この場合、トランザクション2を実行してからトランザクション1を実行した場合、同じ結果が得られるように見えるので、競合の理由は表示されません。 –

答えて

0

一つの方法は、PostgreSQLのAdvisory lockを使用している[1]のメカニズム:あなたは、通常のMVCCの動作は十分ではありませんトランザクション間通信を行うことができます

-- tx 1 
begin; 
select pg_advisory_lock(1234); 
insert/update.... 
commit; 

-- tx 2 
begin; 
select pg_advisory_lock(1234); 
SELECT * FROM weather WHERE city = 'a' FOR SHARE; 
insert/update... 
commit; 

この方法です。この例では、1234はアプリケーションレベルで意味を持つ任意の整数です。また、アドバイザリロックを使用する方法については、[2]を参照してください。

[1] http://www.postgresql.org/docs/9.5/static/explicit-locking.html#ADVISORY-LOCKS

[2] http://www.postgresql.org/docs/9.5/static/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS-TABLE

関連する問題