如何使用perl脚本在mysql中插入时使操作原子化

时间:2015-10-09 04:07:26

标签: mysql perl

我有一个perl脚本,可以为客户下订单。

2桌。

table_orders - orderic, customerid, orderdatetime
table_order_details - orderid, productname, Quantity, MRP. Sellprice

插入表格的步骤:

1. insert in table_orders.
2. for each product in shopping cart insert into table_order_details

现在问题出现在第一张表中,

1. It is possible because of some error in input data insertion in second table is not possible and perl returns an error.
2. Few entries done in table 2 too, but now got the error so further entry not possible in table 2 and perl returns an error.

在这两种情况下,事务未成功完成,那么如何在发生错误之前还原DB中的条目?

是否有perl或MYSQl wat执行此操作或我们需要手动处理它?<​​/ p>

1 个答案:

答案 0 :(得分:3)

使用transactions

事务允许您将更改隔离到数据库,直到您完成所有更改。当您在交易中工作时,没有其他人可以看到这些更改,也没有其他人可以更改这些行。然后你commit交易,其他人都可以一次看到你的更改。如果出现错误,您可以rollback在交易中进行的所有更改。

在Perl中,使用DBI,默认是不使用事务。每个语句都会自动提交。 总是打开交易是非常好主意。您通常通过设置AutoCommit来连接到数据库时执行此操作。您还需要启用RaiseError,因此数据库错误会自动发生,您不必在任何地方写or die...。然后,由于您不想看到错误两次,请关闭PrintError

my $dbh = DBI->connect(
    'dbi:mysql:...', $user, $pass,
    { AutoCommit => 0, RaiseError => 1, PrintError => 0 }
);

现在你所做的一切都将在一次交易中,在你运行$dbh->commit之前,其他任何人都无法看到你所做的一切。将所有工作包装在eval块中,以捕获RaiseError处于打开状态时抛出的任何错误。如果您收到错误,$dbh->rollback将丢弃任何部分工作。

eval {
    my $insert_table_orders_sth = $dbh->prepare(
        "INSERT INTO table_orders (...) VALUES (?, ?, ?)"
    );
    $insert_table_orders_sth->execute(@table_orders_values);

    my $insert_table_orders_details_sth = $dbh->prepare(
        "INSERT INTO table_orders_details (...) VALUES (?, ?, ?)"
    );
    for my $product ($cart->products) {
        $insert_table_orders_details_sth->execute($product->values);
    }

    # All done, make the changes visible to everyone else.
    $dbh->commit;
};
if($@) {
    warn "There was a database error: $@";

    # Wipe out anything you did above.
    eval { $dbh->rollback };

    # Do whatever else you might need to cleanup the error.
}