Java 多线程环境中的ACID问题

Java 多线程环境中的ACID问题,java,mysql,multithreading,innodb,acid,Java,Mysql,Multithreading,Innodb,Acid,我有一个多线程java应用程序,它在MySQL数据库上执行许多并行CRUD操作。正如MySQL手册中所述,InnoDB表结构应确保事务按照ACID原则执行。但我仍然有问题,因为有时更新会丢失。这是我使用的示例存储过程之一: DELIMITER // CREATE PROCEDURE *** ( _*** INT, _*** INT, _*** INT, _*** INT ) BEGIN START TRANSACTION; UPDATE `***`

我有一个多线程java应用程序,它在MySQL数据库上执行许多并行CRUD操作。正如MySQL手册中所述,InnoDB表结构应确保事务按照ACID原则执行。但我仍然有问题,因为有时更新会丢失。这是我使用的示例存储过程之一:

DELIMITER //
CREATE PROCEDURE *** (
    _*** INT,
    _*** INT,
    _*** INT,
    _*** INT
)
BEGIN
  START TRANSACTION;

    UPDATE `***` 
    SET  
      `***`.`***` = `***`.`***` + _***,  
      `***`.`***` = `***`.`***` + _*** + _***,  
      `***`.`***` = DATE_ADD(NOW(), INTERVAL _*** SECOND)  
    WHERE `***`.`***` = _***;

  COMMIT;
END;
// 
DELIMITER ;

JDBC类是不可重入的,因此您必须同步使用connection、statement等对象实例。多个线程不能同时使用它们

使用连接池是简化对数据库的并发访问的好方法

编辑

如果确定线程从未使用相同的连接,则可以检查

  • 池是否可以断开连接?这是怎么处理的
  • 是否有两次更新会在第一次被覆盖的同一条记录上运行
  • 您是否捕获所有异常并将其记录到您的workers中

JDBC类是不可重入的,因此您必须同步使用connection、statement等对象实例。它们不能被多个线程同时保存使用

使用连接池是简化对数据库的并发访问的好方法

编辑

如果确定线程从未使用相同的连接,则可以检查

  • 池是否可以断开连接?这是怎么处理的
  • 是否有两次更新会在第一次被覆盖的同一条记录上运行
  • 您是否捕获所有异常并将其记录到您的workers中

遗憾的是,我已经在使用连接池(BoneCP)。。。我还使用ThreadPoolExecutor来处理执行SQL操作的不同线程——ThreadPoolExecutor使用的工作队列以FIFO方式工作。我认为这两种技术都可以确保对数据库的无错误并发访问。谢谢您的建议!我基本上认为第二个要点导致了问题。。。这就是为什么我认为错误发生在MySQL服务器上,而不是Java连接池/ThreadExecutor上。我还听说MySQL 5.5对InnoDB锁定有更好的支持?这是真的吗?(我仍在使用5.1.x)可悲的是,我已经在使用连接池(BoneCP)。。。我还使用ThreadPoolExecutor来处理执行SQL操作的不同线程——ThreadPoolExecutor使用的工作队列以FIFO方式工作。我认为这两种技术都可以确保对数据库的无错误并发访问。谢谢您的建议!我基本上认为第二个要点导致了问题。。。这就是为什么我认为错误发生在MySQL服务器上,而不是Java连接池/ThreadExecutor上。我还听说MySQL 5.5对InnoDB锁定有更好的支持?这是真的吗?(我仍在使用5.1.x)酸中I的bewate。事务隔离是一个复杂的问题。尝试将事务级别设置为可序列化,以避免在同一行上同时更新,或者设置一些行锁。@regilero:您应该将其作为答案!Vilius:我也读过这篇文章和其他一些关于事务级别的文章,但对我来说仍然不起作用。。。我将重新考虑Java应用程序的设计,并将MySQL服务器更新为ACID中I的5.5 branch.bewate。事务隔离是一个复杂的问题。尝试将事务级别设置为可序列化,以避免在同一行上同时更新,或者设置一些行锁。@regilero:您应该将其作为答案!Vilius:我也读过这篇文章和其他一些关于事务级别的文章,但对我来说仍然不起作用。。。我将重新考虑Java应用程序的设计,并将MySQL服务器更新为5.5分支。