事务是锁定表还是应该将它们锁定在应用程序代码中?

时间:2014-03-11 16:16:48

标签: mysql sql concurrency transactions

我有2张桌子A和B. 在我的应用程序代码中,我更新A中的一些行,然后更新表B,让我们说出我在表A中处理的行数量。
为了简单起见,我在我的应用程序代码中执行以下操作:

dbh->begin;   
my $amount =  0;   
foreach my $item (@item) {  
   my $row = dbh->do("UPDATE A SET VALUE = ?, STATUS = 'processed' WHERE STATUS <> 'processed' and ID = 12", under, $item->{amount});  
   $amount += $item->{amount} if($row);  
}  
if($amount) {  
   dbh->do("UPDATE B SET AMOUNT = ? WHERE id = ?", undef, $amount, 1234);  
}  
$dbh->commit; 

我保持简单(请忽略任何语法错误)以表明这个想法 问题是:
当2个交易同时运行此代码时会发生什么? 理想情况下,我希望以串行模式运行。我怎样才能做到这一点? MySQL使用可重复读取权限吗?

1 个答案:

答案 0 :(得分:1)

  

事务锁定表还是应该将它们锁定在应用程序代码中?

由于您尚未指定您正在使用的存储引擎,因此我将假设InnoDB。内部事务InnoDB uses row-level locking(对于InnoDB,即使启用了自动提交模式,您也始终处于事务中)。您不必使用LOCK TABLES手动锁定InnoDB表;执行语句时,相应的行将自动锁定。

  

当2个交易同时运行此代码时会发生什么?

通过事务,我假设你的意思是线程或进程。这是一种可能的情况:

  1. process1执行第一个UPDATE,在表ID中锁定行A = 12
  2. process2尝试执行第一个UPDATE,但行A.ID = 12被锁定。等待释放锁定
  3. process1执行第二个UPDATE,锁定表ID中的行B = 1234
  4. process1提交事务,释放两个锁
  5. process2获取对行A.ID = 12的锁定并运行UPDATE。由于该值已由process1更新,因此不会更改任何内容并跳过第二个UPDATE
  6. process2提交事务,释放锁定
  7. 请注意,等待锁定时可能会超时。如果发生这种情况,超时的交易将为rolled back