【问题标题】:should I commit in the following code?我应该提交以下代码吗?
【发布时间】:2016-05-11 13:26:42
【问题描述】:

我的代码:

122 #
123 my $hfpDbh = undef;
124 unless (
125         $hfpDbh = DBI->connect("dbi:Pg:host=....")#removed something
128 ) {
129         Log( ERROR, "" );
130         Exit( 1 )
131 }
132 $hfpDbh->{RaiseError} = 1;
133 $hfpDbh->{AutoCommit} = 0;
134 
135 ( my $mydata, $msg ) = load_data( $hfpDbh, $DatFile );
136 unless ( defined($mydata) )
137 {
138         Log(INFO, "Calling exit...2");
139 }
140 #$hfpDbh->disconnect();
141 Exit( 0 );
142 Log(INFO, "Calling exit...4");
143 
144 
145 sub load_data
146 {
147         my ( $dbh, $DatFile ) = @_;
148         my $msg = '';
149         unless ( $dbh ) {
150                 $msg = 'cannot load data, no DB handle';
151                 Log( ERROR, $msg );
152         }
153         Log(INFO, "Call load_data...");
154         my $q = "SELECT ip as ip FROM rules WHERE active = 'true' AND isGood = 'true';";
155         my $stmt = undef;
156         unless ( $stmt = $dbh->prepare( $q ) ) {
157                 $msg = "unable to prepare SQL query: $q";
158                 Log( ERROR, $msg );
159         }
160 
161         eval { $stmt->execute() };
162         if ( $@ ) {
163                 $msg = "failed to execute SQL query: $@";
164                 Log( ERROR, $msg );
165         }
166 
167         my $data = {};
168         while ( my $row = $stmt->fetchrow_hashref() ) {
169                 #Log(INFO, "testing row");
170         }
171         $stmt->finish();
172         return $data, $msg;
173 }

警告是:

Issuing rollback() due to DESTROY without explicit disconnect() of DBD::Pg::db handle

如果我在第 171 行之后添加“$dbh->commit()”,上面的警告就消失了。

如果我没有在第 171 行之后添加“$dbh->commit()”,而是调用了“$hfpDbh->disconnect();”在第 140 行,上面的警告也消失了。

我的问题是: 警告表示有未提交的事务?这就是为什么我需要明确提交或断开连接以修复警告。但是代码中只有 SELECT 操作。我错过了什么?

谢谢。

【问题讨论】:

  • 您的错误处理有点不靠谱。您已经启用了RaiseError,因此您不应该手动检查每种方法的成功与否。如果有错误,RaiseError 会抛出异常。如果您想使用自定义错误处理程序(例如,记录错误),请使用HandleError
  • @ikegami 但 disconnect() 会对未提交的事务进行回滚?我对吗?如果我没有调用 load_data() 函数,即使我没有断开连接,警告也会消失。
  • 另外,你不应该调用finish,并且你应该确保disconnect被调用,即使有异常或信号(例如使用END块和信号处理程序)。

标签: perl postgresql dbi dbd-pg


【解决方案1】:
  • 由于您根本没有修改数据库,因此不需要启用事务,因此不要将AutoCommit 设置为零。这样也不需要在任何地方调用commit,当句柄超出dcope时数据库会自动断开

  • 由于您自己处理错误,因此不应将 RaiseError 设置为 1。如果发生任何错误,这将导致您的程序立即终止,并且您自己的处理代码不会被执行

  • 无需致电finish。它在这里不会造成任何伤害,但它也毫无意义,几乎永远不需要

【讨论】:

  • 如果 AutoCommit 设置为零,是否会启用事务?我需要在 SELECT 之后调用提交或回滚?
  • @BAE:是的,将AutoCommit 设置为零会启用事务。但是您没有修改数据库,因此您不需要它们。禁用事务后,您在任何地方都不需要commitrollback
【解决方案2】:

警告表示有未提交的事务?

自从您请求使用事务以来,有一个未提交的事务,但警告实际上通知您隐式执行了回滚。它会告诉您这一点,因为这可能会导致信息丢失。显然,在这种情况下,它不会导致信息丢失,但支票不够聪明,无法意识到这一点。

我错过了什么?

$hfpDbh->disconnect();$hfpDbh->rollback();

【讨论】:

  • 如果我没有调用 load_data() 函数,即使我没有断开连接,警告也会消失。所以我猜可能有未提交的事务或其他东西,我需要明确地调用提交或断开连接......但我很困惑。
  • 它必须意识到在这种情况下不需要调用rollback,所以它没有。
  • 我记得在python psql 客户端中,commit() 应该被调用,即使只完成了select。
  • @ikegami 如果没有未提交的事务,为什么会隐式执行回滚?
  • @ikegami 谢谢。选择查询?我怎么知道是哪笔交易?
猜你喜欢
  • 1970-01-01
  • 2019-08-06
  • 2016-01-03
  • 1970-01-01
  • 2020-03-08
  • 2019-10-18
  • 2019-11-13
  • 2011-10-06
  • 1970-01-01
相关资源
最近更新 更多