我正在尝试将一些原始DBI调用转换为DBIx :: Class。我偶尔遇到类似的事情:
UPDATE 'foo' SET bar = bar + 1 WHERE ...
有没有办法让DBIx :: Class完全执行这种查询?我不想做类似的事情:
$row->update({ bar => $row->bar() + 1 });
因为如果多个进程试图做同样的事情,就会出现竞争条件。
我可以通过在数据库级别进行某种锁定来解决这个问题,但这对我来说比使用原始查询更糟糕。基本上我只是想知道是否有一种干净的方式使用DBIC来执行此操作,或者我是否应该继续使用原始DBI调用。
答案 0 :(得分:3)
使用来自@ ThisSuitIsBlackNot评论的解决方案,但将update_all
替换为update
:
$rs->search(...)->update({
bar => \'bar + 1',
});
这将导致单个UPDATE语句。 (解释:update_all
通过在ResultSet中的每一行上调用update
来工作,包括DBIC触发器之类的东西,因此它必须首先获取行。在ResultSet上update
执行准系统SQL UPDATE 。)
答案 1 :(得分:0)
使用DBIx :: Class :: Storage :: TxnScopeGuard会有帮助吗?您可以在这样的事务中包装您的代码块
my $guard = $schema->txn_scope_guard;
# your increment
$guard->commit;