如果对更新操作被中断的行执行了更新操作,则postgresql9.0将被锁定并且不响应

时间:2019-02-13 09:10:09

标签: postgresql jdbc locking postgresql-9.0

场景:

  1. 表中有一行id=1
  2. update命令是在第id=1行上用JDBC启动的,但是在获取之前 提交后,建立JDBC连接的Java程序 已终止
  3. 现在,另一个JDBC连接尝试更新同一行id=1

观察:

在监视数据库时,锁很明显,并且在同一行上有进一步的更新操作,导致数据库服务器冻结,必须重新启动才能正常运行...
如果更新查询较少且会话数量较少,则锁会在一分钟内被释放...但是在实际应用中,更新会频繁执行并且服务器会冻结

所以我的问题是:

是否存在一种方法(配置,工具等)来强制,关闭和释放Postgres服务器中的锁,以防止来自客户端的任何无效的数据库连接

代码:

package postgrestest;

import java.sql.*;

public class IncompleteTransvanilla implements Runnable {
    private int seq = 0;
    private Connection connection = null;
    private boolean insertoperation = true;

    public static void main(String[] args) throws Exception{
        boolean flag = true;
        if(args.length>0) {flag = false;}
        for(int i=0;i<10;i++) {
            new Thread(new IncompleteTransvanilla(i,flag)).start();
            //Thread.sleep(1000*(int)(Math.random()*10));
        }
        Thread.sleep(10000);
    }

    public IncompleteTransvanilla(int i, boolean flag) {
        try {
            connection = DriverManager.getConnection("jdbc:postgresql://localhost:5432/testdb", "postgres", "postgres");
            connection.setAutoCommit(false);
        } catch (Exception e) {
            System.out.println("error");
        }
        seq=i;
        insertoperation = flag;
    }

    public void run() {
        try {
            PreparedStatement statement;
            if(insertoperation == true) {
                System.out.println("Inserting");
                statement = connection.prepareStatement("Insert into uacc(user_id,username,password,email) values(DEFAULT,?,'samplepass','samplemail')");
            }
            else {
                System.out.println("Updating");
                statement = connection.prepareStatement("update uacc set username=? where user_id=1");
            }
            int maxval = 100;
            for(int i=0;i<maxval;i++) {
                statement.setString(1, "sampleuser"+((seq*maxval)+i));
                statement.execute();
            }
            Thread.sleep(10000);
            connection.commit();
        } catch (Exception e) {
            System.out.println("Connection failure.");
        }
    }

}

数据库监视破折号屏幕快照,以供参考:

Database Monitoring - pashviewer postgres9.0 locks

编辑: 服务器中是否有任何建议/配置可用于自动删除此类锁或配置,以减少其等待连接并删除锁的时间?

还是...将升级postgres9.0到9.5可以解决这些问题吗?

1 个答案:

答案 0 :(得分:1)

要防止客户端在工作中突然死亡,可以使用以下PostgreSQL参数:

  • tcp_keepalives_idle:将其设置为60之类的较低值,以便服务器在闲置一分钟后对其进行探测,并在客户端死机时终止会话。

  • idle_in_transaction_session_timeout:将此值设置为甚至更低的值,因为任何事务都不应长时间保持空闲状态。这将杀死持有锁的空闲会话。注意,不要破坏数据库的正常活动!

从9.0升级应该是您的首要任务,因为9.0的版本过旧且不受支持。不过更新到v11而不是9.5。