【发布时间】:2020-07-08 21:09:56
【问题描述】:
我有一个方法 boolean addIntegerColumnToDatabases(String tableName, String columnName, Connection ... conns) 我有一个 SQL 连接集合。
对于每个 SQL 连接,我都会执行 schema-update-query
BEGIN
ALTER TABLE <b>tableName</b> ADD COLUMN <b>columnName</b> int4
COMMIT
由于此方法必须是 ACID,因此我喜欢并行执行此操作。
例如,我有两个连接(C1、C2):
C1:开始
C2:开始
C1: ALTER TABLE tableName 添加列 columnName int4
C2: ALTER TABLE tableName 添加列 columnName int4
C1:提交
C2:提交
这是代码:
Statement[] s = new Statement[conns.length];
int i =0;
for(Connection c:conns) {
c.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
c.setAutoCommit(false);
s[i++]=c.createStatement();
}
for(Statement st:s) {
st.executeUpdate("ALTER TABLE "+tableName+" ADD COLUMN "+columnName+" int4;");
}
for(Connection c:conns) {
c.commit();
}
return true;
只要连接在不同的数据库上,此方法就可以工作。
问题
如果 C1 和 C2 连接到同一个数据库,C2 在 Postgres 端等待 C1 提交,C1 在 Java 端等待 C2。瞧,我们陷入了僵局。
由于集群/平衡、ipv4/6 和 dns 问题等问题,我没有 100% 的机会检查连接是否指向同一个数据库系统。
问题
如果执行有两个连接到同一个数据库而不执行任何架构更改,如何确保return false;?
【问题讨论】:
-
不相关,但是:
c.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);在 Postgres 中没用,因为它不支持脏读。 -
您知道像 Liquibase 这样的架构迁移工具已经解决了这个问题吗? (还有更多)
-
@a_horse_with_no_name 我不喜欢 liquibase,它的架构很脏。
-
10 多年来,我在大约 20 个项目中运行良好。
-
@a_horse_with_no_name 我相信它在 20 多个项目中为更多人服务了 10 多年。不会改变它的架构很脏的事实。我的意思是谁实际上进行版本控制?谁是并发版本控制(git,svn,cvs)或changelog-xmls或数据库或所有这些的权威?谁在差异的情况下胜出,是数据库还是变更日志?
标签: java sql postgresql transactions deadlock