java - 并发进程向数据库中插入数据

标签 java postgresql jdbc transactions

考虑 postgres 数据库中的以下模式。

CREATE TABLE employee
(
  id_employee serial NOT NULL PrimarKey,
  tx_email_address text NOT NULL Unique,
  tx_passwd character varying(256)
)

我有一个 java 类执行以下操作

conn.setAutoComit(false);

ResultSet rs = stmt.("select * from employee where tx_email_address = 'test1'");
if (!rs.next()) {
    Insert Into employee Values ('test1', 'test1');
}
ResultSet rs = stmt.("select * from employee where tx_email_address = 'test2'");
if (!rs.next()) {
    Insert Into employee Values ('test2', 'test2');
}
ResultSet rs = stmt.("select * from employee where tx_email_address = 'test3'");
if (!rs.next()) {
    Insert Into employee Values ('test3', 'test3');
}
ResultSet rs = stmt.("select * from employee where tx_email_address = 'test4'");
if (!rs.next()) {
    Insert Into employee Values ('test4', 'test4');
}

conn.commit();
conn.setAutoComit(true);

这里的问题是,如果上面提到的事务有两个或多个并发实例试图写入数据。只有一个事务最终会成功,其余事务将抛出 SQLException“违反唯一键约束”。我们如何解决这个问题。

PS:我只选择了一个表和简单的插入查询来演示问题。我的应用程序是基于 java 的应用程序,其唯一目的是将数据写入目标数据库。并且可能有并发进程这样做,并且某些进程可能试图写入相同数据的可能性非常高(如上例所示)。

最佳答案

最简单的方法似乎是使用事务隔离级别“可序列化”,它可以防止幻读(其他人插入满足您事务期间先前 SELECT 的数据)。

if (!conn.getMetaData().supportsTransactionIsolationLevel(Connection.TRANSACTION_SERIALIZABLE)) {
    // OK, you're hosed. Hope for your sake your drivers supports this isolation level 
}
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);

还有诸如 Oracle 的“MERGE”语句之类的技术——根据数据是否存在,执行“插入或更新”的单个语句。我不知道 Postgres 是否有等价物,但有一些技术可以“伪造”它——参见例如 How to write INSERT IF NOT EXISTS queries in standard SQL .

关于java - 并发进程向数据库中插入数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1125117/

相关文章:

java - 无法在 ubuntu 中访问 graph.db

java - 创建一个带有 3 个单选按钮和一个提交按钮的基本框架

python - 将 Postgresql 表导出为带有标题的 excel

postgresql - 由同一组的用户拥有的 ALTER postgres 表

java - 如何在 hibernate 中使用数据库系统日期

java - 如何将Spring Web服务上线?

java - 一步将数据从 Postgres DB 复制到 AWS S3

java.sql.SQLException :field id does not have a default value

java - Spring Bean : DriverManagerDataSource converting to sun. jdbc.odbc.ee.DataSource

oracle - 如何使用JRuby和JDBC连接到Oracle