Perl DBI begin_work 和与 SQL Server 2008 交互的嵌套事务
我有一个像下面这样的场景。其中 main 方法需要调用多个方法,1 个表调用 1 个方法,每个方法运行一组必须是原子的语句。因此它们被包含在 begin_work、commit、rollback 块中。
另外,call_method_for_table1、call_method_for_table2、call_method_for_table3 应该全部成功或失败,这意味着它们必须是原子的。这就是为什么在 main 方法中也添加了 begin_work、commit、rollback 块的原因。但我可以看到 perl 不允许我。我收到异常 - “DBD::ODBC::db begin_work 失败:已在事务中”。现在我没有任何方法可以修改 call_method_for_table* 方法,因为它位于库中,并且由于多种原因无法修改它。
我可以使用检查点来解决此问题
- 保存点会有所帮助吗(http://msdn.microsoft.com/en-us/library/ms378414%28v=SQL.105%29.aspx)
- 将回滚直到保存点工作,即使有一些提交在两者之间(在我的示例中通常是这种情况)
- 即使同一进程并行运行也可以吗?
- 会不会造成数据不一致?
子主{ $dbh->begin_work; 评估{ call_method_for_table1(); call_method_for_table2(); call_method_for_table3(); $dbh->提交; 1; }; 如果($@){ $dbh->回滚; } } 子 call_method_for_table1 { $dbh->begin_work; 评估{ $dbh->do($INSERTSTATEMENT_TABLE1); $dbh->do($UPDATESTATEMENT_TABLE1); $dbh->do($DELETESTATMENT_TABLE1); $dbh->提交; }; 如果($@){ $dbh->回滚; } }
I have a scenario like below. Where the main method needs to call multiple methods , 1 method for 1 table , and each method runs a set of statements which has to be atomic. So they are enclosed within a begin_work,commit,rollback block.
Also call_method_for_table1,call_method_for_table2,call_method_for_table3 should all succeed or fail together which means they have to be atomic. That is why begin_work,commit,rollback block are added in main method also. But i can see that perl does not allow me . I get exception - "DBD::ODBC::db begin_work failed: Already in a transaction". Now i do not have any way of modifying the call_method_for_table* methods since it is in a library and modifying it is not possible due to many reasons.
Can i use checkpoints to solve this problem
- Will Savepoints help (http://msdn.microsoft.com/en-us/library/ms378414%28v=SQL.105%29.aspx)
- Will Rolling back till savepoint work even if there are some commits in between (which is usually the case in my example)
- Is it fine even when there are parallel runs of the same process ?
- Will it cause data inconsistency?
sub main { $dbh->begin_work; eval { call_method_for_table1(); call_method_for_table2(); call_method_for_table3(); $dbh->commit; 1; }; if ($@) { $dbh->rollback; } } sub call_method_for_table1 { $dbh->begin_work; eval { $dbh->do($INSERTSTATEMENT_TABLE1); $dbh->do($UPDATESTATEMENT_TABLE1); $dbh->do($DELETESTATEMENT_TABLE1); $dbh->commit; }; if ($@) { $dbh->rollback; } }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为不修改
call_method_for_tableX
是不可能的。假设
call_method_for_table1
成功,则提交已完成,并且在call_method_for_table2
最终失败后无法回滚。I think it's impossible without modifying the
call_method_for_tableX
.Suppose
call_method_for_table1
succeeds, then the commit is done and you can't rollback aftercall_method_for_table2
eventually failed.