[MTOS-dev] Making MT Transaction Safe
Hirotaka Ogawa
hirotaka.ogawa at gmail.com
Tue Mar 11 02:48:16 PDT 2008
On Tue, Mar 11, 2008 at 5:31 PM, Alvar Freude <alvar at a-blast.org> wrote:
> Hi,
>
> -- Hirotaka Ogawa <hirotaka.ogawa at gmail.com> wrote:
>
>
> >> > Why not enabling transactions by default, when an appropriate
> >> > RDBMS or table type is used?
> >>
> >> Because, no commits and rollbacks are inserted into MT code. That is,
> >> no changes occurs if enabling this option.
>
> I mean: when everything works with transactions, it sounds better to
> enable them by default. When not working, it is surely better not to
> enable it ;-)
okay ;-)
> > Or, we can extend MT::Object->save() method so as to store data with
> > commits and rollbacks by default, and store without commits/rollbacks
> > optionally. For example, $obj->save() to be committable write, and
> > $obj->save({ nocommit => 1}) to be non-committable write.
> >
> > Ah, this may be a good idea. We can make MT transaction-safe
> > gradually and safely.
>
> yes, this sounds better!
>
> What about exception handling: is there something usual in MT, like the
> usual DBI eval + commit/rollback block?
>
> Perhaps something similar should be added.
Yep. I've not tested, but we can do as like:
unless ($options->{nocommit}) {
eval {
$sth->execute;
};
if ($@) {
$driver->rollback;
Carp::croak("INSERT error $driver: $@");
}
$driver->commit;
} else {
$sth->execute;
}
$sth->finish;
> >> > hmmm, and why not selecting InnoDB as default?
> [...]
>
> >> Why can it be default?
> >>
> >> I've just made it possible to try using transaction feature for MySQL
> >> people. Before making it be default, we need to support doing
> >> "transactions" and altering MyISAM tables to InnoDB, and so on.
>
> same as above: it should not be the default until it is ready, sure! :)
>
> But InnoDB can also be used with AutoCommit => 1, like PostgreSQL.
Right. Let me clarify the situation.
When AutoCommit => 1, we also need to insert $dbh->begin_work() to
define the beginnings of transactions. In this case, we don't have to
have commitable-save as I mentioned above, but need to define
transaction sections explicitly and manually. But, it will be done
gradually as required. Assuming the case that we save entry data and
its trackback data:
sub save {
my $entry = shift;
...
$entry->SUPER::save();
my $tb = MT::Trackback->new;
$tb->entry_id($entry->id);
$tb->save();
}
We need to rewrite this as like (this is a pseudo code):
sub save {
my $entry = shift;
...
MT::ObjectDriverFactory->begin_work;
eval {
$entry->SUPER::save();
my $tb = MT::Trackback->new;
$tb->entry_id($entry->id);
$tb->save();
};
if ($@) {
MT::ObjectDriverFactory->rollback;
return $entry->error($@);
}
MT::ObjectDriverFactory->commit;
}
When AutoCommit => 0, the beginnings of transactions are implicitly
and automatically defined, namely at the point connection established
and the point just after previous commit succeeded. In this case, by
using commitable-save hack, we can just do as like:
sub save {
my $entry = shift;
...
$entry->SUPER::save({ nocommit => 1 }); # add nocommit option
my $tb = MT::Trackback->new;
$tb->entry_id($entry->id);
$tb->save();
}
Which is better?
I think the former is better, because we can easily and explicitly see
how transactions handle in MT Core. The latter is surely easy to
code, but too implicit, I guess.
--
Hirotaka Ogawa makes no sense.
http://as-is.net/blog/
More information about the MTOS-dev
mailing list