簡體   English   中英

PostgreSQL永遠掛在可序列化事務上

[英]postgresql hang forever on serializable transaction

我使用libpqxx連接到PostgreSQL。 一切正常,直到我在一行的一張表上運行serialazable查詢。

表:

CREATE TABLE t1(id integer primary key);

的postgres 9.4.4_x64

pqxx::connection c1(conn_str);
pqxx::connection c2(conn_str);

pqxx::transaction<pqxx::isolation_level::serializable> t1(c1);
t1.exec("INSERT INTO t1 (id) VALUES (25)");

pqxx::transaction<pqxx::isolation_level::serializable> t2(c2);
t2.exec("INSERT INTO t1 (id) VALUES (25)"); //hang here

t2.commit();
t1.commit();

我的程序永遠掛起。 掛在PQexec函數中。 為什么? 我是否認為必須回滾交易之一? 但不是? 掛了

更新:純libpq的結果相同:

c1 = PQconnectdb(conninfo);
c2 = PQconnectdb(conninfo);

res1 = PQexec(c1, "BEGIN");
PQclear(res1);


res1 = PQexec(c1, "INSERT INTO t1 (id) VALUES (104)");
PQclear(res1);

res2 = PQexec(c2, "BEGIN");
PQclear(res2);

res2 = PQexec(c2, "INSERT INTO t1 (id) VALUES (104)");
PQclear(res2);

res2 = PQexec(c2, "END");
PQclear(res2);

res1 = PQexec(c1, "END");
PQclear(res1);

PostgreSQL 9.1-相同的掛起

掛起與可serializable隔離級別無關。

我不是libpqxx專家,但是您的示例似乎在單個線程中運行了兩個事務。 那是你的問題。

t2.exec("INSERT INTO t1 (id) VALUES (25)");

上面的語句必須等待t1提交或回滾才能完成,但是t1.commit()永遠沒有機會執行。 僵局! 這絕對是正常的,並且無論您選擇的隔離級別如何,都會發生這種情況。 這只是試圖在同一執行線程中從2個並發事務中運行語句的結果,不是一個好主意。

嘗試在不同的線程上運行兩個事務,您的掛起將消失。

如果僅涉及兩個事務,則應該獲得事務t2的唯一違規錯誤-與默認的READ COMMITTED隔離級別完全相同

 ERROR: duplicate key value violates unique constraint "t1_pkey" DETAIL: Key (id)=(25) already exists. 

t1首先嘗試插入,然后不管哪個事務首先嘗試提交均獲勝。 接下來的所有嘗試插入相同密鑰的事務都將等待第一個事務。 同樣,這對於READ COMMITTEDSERIALIZABLE都是有效的。

可能的解釋是,涉及到第三筆交易該筆交易試圖首先插入相同的密鑰,但仍處於打開狀態。 或幾次這樣的交易,即測試的人工制品。

所有事務都等待一個嘗試插入相同密鑰的事務。 如果提交,則其他所有都將發生唯一違規。 如果它回滾,那么下一行將獲得機會。

要檢查一下pg_stat_activity (已連接到同一數據庫):

SELECT * FROM pg_stat_activity;

進一步來說:

SELECT * FROM pg_stat_activity WHERE state = 'idle in transaction';

然后提交/回滾空閑事務。 還是蠻力的:終止該連接。 細節:

組建Postgres小組:

“在並發編程中,死鎖是這樣一種情況,其中兩個或更多競爭的動作各自在等待對方完成,因此永遠不會。” https://en.wikipedia.org/wiki/Deadlock

定義首先不是死鎖。 “ c1”不等待“ c2”完成,可以愉快地進行id = 104的業務。 但是,您的應用程序永遠不會給c1下一條命令,因為它頑固地等待“ c2”執行其插入-由於“ c1”持有的鎖,它無法執行該操作。

鎖測試可以在單個線程中完成,但是死鎖測試意味着兩個連接都需要同時嘗試執行命令-如果沒有線程,單個程序就無法完成。

戴維·J。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM