我有一个多线程 java 进程,运行 2 个数据库事务,如下所示:
. . dbop1(); . . . dbop2(); . .
当我终止进程(在 Linux 上使用 kill)时,数据库可能会失去完整性,因为程序可能会在 dbop1() 和 dbop2() 之间终止。
是否有办法捕获终止信号然后优雅地终止?例如,如果 kill 介于两者之间,我仍然希望完成 dbop2() 然后终止。
出于性能方面的考虑,我对在单个事务中进行 2 db 事务犹豫不决。
我假设如果 kill 在数据库事务期间发生,数据不会损坏,这是真的吗?
此外,dbop1() 和 dbop2() 是像下面这样的 hibernate 包装器:
try{ beginTransaction(); getSession().save(obj); //sessionFactory.openSession().save(obj); commitTransaction(); } catch(Exception e){ e.printStackTrace(); rollbackTransaction(); throw e; }finally{ closeSession(); }
最佳答案
正如您已经提到的,这里正确的方法是将两个 db 语句都放在一个事务中,因为其他任何事情都很可能存在完整性问题。这可能取决于您的特定用例,但完整性问题通常比您在这里可能遇到的任何性能问题重要得多。
这超出了通过 kill
杀死应用程序的原因,因为第二个 db 语句可能有异常,应用程序可能在它们之间崩溃,或者服务器/网络可能有一个问题等等。所以最佳实践肯定是将两个语句放入一个事务中。
现在,综上所述,可以根据 kill 级别来阻止 kill 语句,也许可以通过注册一个等待(或阻止)直到两个语句完成的关闭 Hook 。但是,我不推荐这样做,因为 kill -9
会像上面提到的其他可能性一样完全跳过它。
例如(仅出于完整性考虑,因为我真的根本不推荐下面的代码)。
使用 ReentrantReadWriteLock
以某种方式通过 sharedState
共享(可以设置到下面的关闭 Hook 中,或者如果您真的愿意,它也可以是单例)。
Runtime.getRuntime.addShutdownHook(new Thread() {
public void run()
{
sharedState.rwl.writeLock().lock();
System.out.println("We are shutting down!");
// Hopefully holding this lock does not prevent our shutdown
// I.e. no other thread needs it to complete gracefully
}
}
和
try
{
sharedState.rwl.readLock().lock();
dbOp1;
dbOp2;
} finally
{
sharedState.rwl.readLock().unlock();
}
其中 sharedState
代表某种机制,您可以通过该机制在关闭 Hook 和运行数据库操作的代码之间共享 rwl。
关于java - 使用数据库读写杀死多线程操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24899683/