This queue is for tickets about the DBD-Multiplex CPAN distribution.

Report information
The Basics
Id:
19266
Status:
resolved
Priority:
Low/Low
Queue:

People
Owner:
tkishel+perl [...] gmail.com
Requestors:
rhesa [...] cpan.org
Cc:
AdminCc:

BugTracker
Severity:
Normal
Broken in:
1.98
Fixed in:
(no value)



Subject: Add transaction support
Hi Thomas, I'm using DBD::Multiplex in a MySQL replication setup. As you may know, records created in a transaction aren't replicated to slaves until the transaction is commited. This means that SELECTs for those records would fail when issued on any slave. The attached patch adds a minimum amount of support for transactions. The result of the new code is that transactions are run against the mx_master handle only. I haven't made any changes to the POD, since I feel this change is too small to really mention. It's merely a little more DWIM. Rhesa
Subject: transaction_support.diff
--- Multiplex.pm 2005-10-24 17:57:54.000000000 +0200 +++ Multiplex.pm.new 2006-05-15 18:19:20.415682270 +0200 @@ -148,7 +148,7 @@ # the above condition is wrong, because then _any_ prepare() # will definitely go to second condition. - if ($parent_handle->{'mx_master_id'} && &DBD::Multiplex::mx_is_modify_statement(\$statement)) { + if ($parent_handle->{'mx_master_id'} && ( &DBD::Multiplex::mx_is_modify_statement(\$statement) or not $parent_handle->{AutoCommit} )) { # TK Note: # Loop to find the master handle.
From: tkishel+perl@gmail.com
Rhesa, Added, as v1.99, with slightly different syntax. Please verify after the upload is processed. -- Tom
Show quoted text
> Hi Thomas, > > I'm using DBD::Multiplex in a MySQL replication setup. As you may know, > records created in a transaction aren't replicated to slaves until the > transaction is commited. This means that SELECTs for those records would > fail when issued on any slave. > > The attached patch adds a minimum amount of support for transactions. > The result of the new code is that transactions are run against the > mx_master handle only. > > I haven't made any changes to the POD, since I feel this change is too > small to really mention. It's merely a little more DWIM. > > Rhesa
Subject: Re: [rt.cpan.org #19266] Add transaction support
Date: Wed, 17 May 2006 21:27:36 +0200
To: bug-DBD-Multiplex@rt.cpan.org
From: Rhesa Rozendaal <rhesa@cpan.org>
Hi Tom, I upgraded and tested (for as much as I could), and it looks perfect. I'm already using it in production and everything just hums along. Thanks! Rhesa
Show quoted text
> > Rhesa, > > Added, as v1.99, with slightly different syntax. Please verify after the upload is processed. > > -- Tom > >
Subject: Re: [rt.cpan.org #19266] Add transaction support
Date: Mon, 29 May 2006 19:13:01 +0200
To: bug-DBD-Multiplex@rt.cpan.org
From: Rhesa Rozendaal <rhesa@cpan.org>
Hi Tom, It turns out my previous patch was way too naive. Its result is that _every_ query is run against the master. Here's why: - the $parent_handle in mx_do_calls is either a DBD::Multiplex::db, or a statement handle - D::M doesn't set the AutoCommit field on itself (it passes it on to the child dbh's) - the result is that $parent_handle->{AutoCommit} is always false at prepare() time, causing it to run against the mx_master I'm currently testing the following condition instead: ( scalar grep { defined && $_->isa('DBI::db') && (! $_->{'AutoCommit'}) } @$parent_handle_list ) I've verified that this restores the old behaviour, where selects are performed against the first_success-ful child, and modify statements are run against the master. I've also tested the behaviour under transactions, and I think it is alright now. If DBD::Multiplex would set attributes like AutoCommit on itself (in DBD::Multiplex::db::STORE), the check could also be written as ( $parent_handle->isa('DBI::db') && !$parent_handle->{AutoCommit} ) The grep{} looks less intrusive though. I have attached a diff against 1.99. Feel free to undo the changes I made in the trace_msg calls, I just needed those to see what was going on. I have also attached a test script, including DBI_TRACE=2 output. The test contains some private data, but I don't consider that a big problem. The master and slave03 were hot, while slave01 was stopped expressly to show that selects in non-transactional mode would go to slaves, while those inside transactions would go against the master. Note that several runs pick up the master as the first_success_random child, which effectively defeats the purpose of replication. I'm considering using first_success instead, putting my mx_master last. This might be something worth mentioning in the documentation. Oh, I would have loved to provide you with an actual unit test, but I have no idea how to setup a replicated environment on the fly. I suppose I could come up with something built on DBD::Mock or Test::MockDBI, but it'd probably take quite a bit of puzzling. Let me know if you'd like to have it. I personally very much need to know that this stuff works, so I'm willing to invest more time and effort. I hope the attached data provides you with enough information to see that the current patch is actually functional. Rhesa
Show quoted text
> <URL: http://rt.cpan.org/Ticket/Display.html?id=19266 > > > Rhesa, > > Added, as v1.99, with slightly different syntax. Please verify after the upload is processed. > > -- Tom > >
>>Hi Thomas, >> >>I'm using DBD::Multiplex in a MySQL replication setup. As you may know, >>records created in a transaction aren't replicated to slaves until the >>transaction is commited. This means that SELECTs for those records would >>fail when issued on any slave. >> >>The attached patch adds a minimum amount of support for transactions. >>The result of the new code is that transactions are run against the >>mx_master handle only. >> >>I haven't made any changes to the POD, since I feel this change is too >>small to really mention. It's merely a little more DWIM. >> >>Rhesa
> > > > >
--- Multiplex.pm 2006-05-15 13:51:11.000000000 -0700 +++ /usr/lib/perl5/site_perl/5.8.5/DBD/Multiplex.pm 2006-05-29 09:41:22.000000000 -0700 @@ -135,7 +135,7 @@ $exit_mode = $multiplex_options->{'exit_mode'} || 'first_error'; $error_proc = $parent_handle->{'mx_error_proc'}; - $parent_handle->trace_msg("mx_do_calls $method for " . join(", ", map{defined $_?$_:''} @$parent_handle_list) . "\n"); + $parent_handle->trace_msg("mx_do_calls $method on $parent_handle for " . join(", ", map{defined $_?$_:'{undef}'} @$parent_handle_list) . " at " . __PACKAGE__ . " " . __LINE__ . "\n"); $child_number = 0; $statement = $parent_handle->{'Statement'}; @@ -152,9 +152,13 @@ # Transactions are run only on the master. if ( $parent_handle->{'mx_master_id'} && - ( &DBD::Multiplex::mx_is_modify_statement(\$statement) || (! $parent_handle->{'AutoCommit'}) ) - ) { + ( &DBD::Multiplex::mx_is_modify_statement(\$statement) + || + ( scalar grep { defined && $_->isa('DBI::db') && (! $_->{'AutoCommit'}) } @$parent_handle_list ) # RR: do we have child db handles with AutoCommit off? + ) + ) { + $parent_handle->trace_msg('this one runs against master because ' . ((!$parent_handle->{'AutoCommit'}) ? " autocommit is off on parent $parent_handle: $parent_handle->{'AutoCommit'}" : (&DBD::Multiplex::mx_is_modify_statement(\$statement) ? "$statement is deemed a modify" : ' eh?! ' ) ) . "\n" ); # TK Note: # Loop to find the master handle. # Consider finding once and storing rather than finding each time. @@ -165,7 +169,7 @@ } if ($statement) { - $parent_handle->trace_msg("mx_do_calls $method for statement $statement against child number $child_number\n"); + $parent_handle->trace_msg("mx_do_calls $method for statement $statement against child number $child_number at " . __PACKAGE__ . " " . __LINE__ . "\n"); } $child_handle = $parent_handle_list->[$child_number]; @@ -192,6 +196,10 @@ $parent_handle->trace_msg("mx_do_calls $method for statement $statement against child number $child_number\n") ; } + # RR Note: + # make sure the child_handle is defined + $child_number++, next unless defined $child_handle; + # Here, the actual method being multiplexed is being called. push @results, ($wantarray) ? [ $child_handle->$method(@_) ]

Message body not shown because it is not plain text.

Addressed in v 1.99. -- Tom


This service runs on Request Tracker, is sponsored by The Perl Foundation, and maintained by Best Practical Solutions.

Please report any issues with rt.cpan.org to rt-cpan-admin@bestpractical.com.