2011-11-12 238 views
0

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

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

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

    COMMIT; 
END; 
// 
DELIMITER ; 
+1

在ACID中的I的bewate。交易隔离是一个复杂的问题。尝试将事务级别设置为可串行化以避免同一行上的并发更新,或者放置一些行锁。 – regilero

+0

@regilero:你应该把它作为答案! Vilius:也请阅读:http://www.mpopp.net/2005/12/tx-isolation-levels-3-repeatable-read-serializable/ –

+0

我已经阅读了关于交易级别的文章和一些其他文章,但仍然不适合我...我将重新考虑Java应用程序的设计,并将MySQL服务器更新到5.5分支。 – Vilius

回答

3

JDBC类是不可重入,所以你必须使用连接,语句等的对象实例同步它们不能savely被多个线程使用同时。

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

编辑

如果你确定线程永远不会使用相同的连接,你可以检查

  • 可以在泳池出来的连接?这是如何处理的?
  • 是不是2次更新会对第一次被覆盖的记录起作用?
  • 你是否捕捉到所有异常并将它们记录在工人中?
+0

可悲的是,我已经在使用连接池(BoneCP)...我还使用ThreadPoolExecutor来处理执行SQL操作的不同线程 - 用于ThreadPoolExecutor的工作队列以FIFO方式工作。我认为这两种技术都可以确保对数据库的并发访问无误。 – Vilius

+0

@Villius,请参阅编辑 – rsp

+0

感谢您的建议!我基本上认为第二个重点导致了这些问题......这就是为什么我相信错误发生在MySQL服务器而不是Java Connection Pool/ThreadExecutor。我也听说MySQL 5.5对InnoDB锁定有更好的支持吗?这是真的吗? (我仍然在使用5.1.x) – Vilius