我使用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函数中。为什么?我认为它必须回滚一个交易吗?但不是?只是挂起。
UPDATE:纯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 - 同样挂起
答案 0 :(得分:0)
如果仅涉及两个事务,则应该为事务 t2 - 与默认READ COMMITTED
隔离级别完全相同的获取唯一的违规错误:
ERROR: duplicate key value violates unique constraint "t1_pkey" DETAIL: Key (id)=(25) already exists.
t1 首先尝试插入并获胜,无论哪个事务首先尝试提交。尝试插入相同密钥的所有后续事务等待第一个。同样,这适用于READ COMMITTED
和SERIALIZABLE
等。
可能的解释 将涉及第三个交易,它试图先插入相同的密钥并仍然打开。或几个这样的交易,你的测试的人工制品。
所有交易等待第一个试图插入相同密钥的交易。如果那个提交,所有其他人都会获得一次独特的违规行为。如果它回滚,那么下一个就有机会。
查看pg_stat_activity
(连接到相同的数据库):
SELECT * FROM pg_stat_activity;
更具体地说:
SELECT * FROM pg_stat_activity WHERE state = 'idle in transaction';
然后提交/回滚空闲事务。或暴力:终止该连接。详细说明:
答案 1 :(得分:0)
组建postgres团队:
“在并发编程中,死锁是指两个或多个竞争行为各自等待另一个完成的情况,因此两者都没有。” https://en.wikipedia.org/wiki/Deadlock
定义它首先不是僵局。 “c1”不等待“c2”完成,并且可以愉快地开展id = 104的业务。但是,你的应用程序永远不会给c1下一个命令,因为它固执地等待“c2”执行它的插入 - 由于“c1”持有锁,它不能。
锁定测试可以在一个线程内完成,但死锁测试意味着两个连接都需要同时尝试执行命令 - 单个程序无法在没有线程的情况下完成。
David J。