From 1342eb3b95122e16d20b607783b869df4db124b1 Mon Sep 17 00:00:00 2001 From: Greg Sabino Mullane Date: Fri, 1 Mar 2013 16:04:23 -0500 Subject: [PATCH] Allow transaction isolation level to be changed --- Bucardo.pm | 7 ++++++- bucardo | 36 +++++++++++++++++++++++++++++------- bucardo.schema | 5 +++++ 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/Bucardo.pm b/Bucardo.pm index 99363536..b4d3703d 100644 --- a/Bucardo.pm +++ b/Bucardo.pm @@ -2877,6 +2877,11 @@ sub start_kid { ## Add a note to the syncrun table $sth{kid_syncrun_update_status}->execute("Begin txn (KID $$)", $syncname); + ## Figure out our isolation level. Only used for Postgres + ## All others are hard-coded as 'serializable' + my $isolation_level = defined $sync->{isolation_level} ? $sync->{isolation_level} : + $config{isolation_level} || 'serializable'; + ## Commit so our dbrun and syncrun stuff is visible to others ## This should be done just before we start transactions on all dbs $maindbh->commit(); @@ -2893,7 +2898,7 @@ sub start_kid { $x->{dbh}->rollback(); if ($x->{dbtype} eq 'postgres') { - $x->{dbh}->do('SET TRANSACTION ISOLATION LEVEL SERIALIZABLE READ WRITE'); + $x->{dbh}->do(qq{SET TRANSACTION ISOLATION LEVEL $isolation_level READ WRITE}); $self->glog(qq{Set database "$dbname" to serializable read write}, LOG_DEBUG); } diff --git a/bucardo b/bucardo index 1b0ad524..3c88c24d 100755 --- a/bucardo +++ b/bucardo @@ -3639,6 +3639,7 @@ sub add_sync { onetimecopy onetimecopy =0|1|2 null lifetime lifetime interval null maxkicks maxkicks numeric null + isolation_level|txnmode isolation_level 0 null rebuild_index|rebuildindex rebuild_index numeric null tables tables 0 skip }; @@ -3653,6 +3654,10 @@ sub add_sync { value => 'fullcopy', new_defaults => 'autokick|F stayalive|F kidsalive|F', }, + { + field => 'isolation_level', + dash_to_white => 1, + } ]; my ( $dbcols, $cols, $phs, $vals ) = process_simple_args({ @@ -3998,7 +4003,10 @@ sub update_sync { die "Invalid setting: $setting\n"; } - ## Normalize things like t/f 0/1 others? + ## Do any magic we need + if ($setting eq 'isolation_level') { + $value =~ s/_/ /g; + } ## Try setting it $SQL = "UPDATE sync SET $setting=? WHERE name = ?"; @@ -8102,11 +8110,15 @@ sub process_simple_args { for my $mline (@{$arg->{morph}}) { if (exists $mline->{field}) { next unless exists $dbcol{$mline->{field}}; - next if $dbcol{$mline->{field}} ne $mline->{value}; - for my $change (split /\s+/ => $mline->{new_defaults}) { - my ($f,$v) = split /\|/ => $change; - next if exists $dbcol{$f}; - $dbcol{$f} = $v; + if (exists $mline->{new_defaults}) { + for my $change (split /\s+/ => $mline->{new_defaults}) { + my ($f,$v) = split /\|/ => $change; + next if exists $dbcol{$f}; + $dbcol{$f} = $v; + } + } + if (exists $mline->{dash_to_white}) { + $dbcol{$mline->{field}} =~ s/_/ /g; } } else { @@ -10077,7 +10089,7 @@ what to replicate from where to where. The supported parameters are: =item C -The name of the sync. +The name of the sync. Required. =item C @@ -10104,6 +10116,11 @@ Number of seconds a KID can live before being reaped. Number of times a KID may be kicked before being reaped. +=item C + +The transation isolation level this sync should use. +Only choices are "serializable" and "repeatable read" + =item C The conflict resolution strategy to use in the sync. Supported values: @@ -10449,6 +10466,11 @@ Directory to store the flatfile output inside of. Default: C<.>. Regex to make sure we don't accidentally run where we should not. Default: None. +=item C + +The transaction isolation level all sync should use. Defaults to 'serializable'. +The only other valid option is 'repeatable read' + =item C How long to sleep in seconds if we hit a deadlock error. Default: C<0.5>. diff --git a/bucardo.schema b/bucardo.schema index d6f52206..a5b76dcf 100644 --- a/bucardo.schema +++ b/bucardo.schema @@ -161,6 +161,7 @@ default_conflict_strategy|bucardo_latest|Default conflict strategy for all syncs email_debug_file||File to save a copy of all outgoing emails to flatfile_dir|.|Directory to store the flatfile output inside of host_safety_check||Regex to make sure we don't accidentally run where we should not +isolation_level|serializable|Default isolation level: can be serializable or repeatable read piddir|/var/run/bucardo|Directory holding Bucardo PID files reason_file|bucardo.restart.reason.txt|File to hold reasons for stopping and starting semaphore_table|bucardo_status|Table to let apps know a sync is ongoing @@ -405,6 +406,7 @@ CREATE TABLE bucardo.sync ( onetimecopy SMALLINT NOT NULL DEFAULT 0, lifetime INTERVAL NULL, -- force controller and kids to restart maxkicks INTEGER NOT NULL DEFAULT 0, -- force controller and kids to restart + isolation_level TEXT NULL DEFAULT 'serializable', cdate TIMESTAMPTZ NOT NULL DEFAULT now() ); COMMENT ON TABLE bucardo.sync IS $$Defines a single replication event from a herd to one or more target databases$$; @@ -419,6 +421,9 @@ ALTER TABLE bucardo.dbgroup ADD CONSTRAINT dbgroup_name_sane CHECK (name ~ E'^[a ALTER TABLE bucardo.sync ADD CONSTRAINT sync_name_sane CHECK (name ~ E'^[a-zA-Z]\\w*$' AND lower(name) NOT IN ('pushdelta','fullcopy','swap')); +ALTER TABLE bucardo.sync ADD CONSTRAINT sync_isolation_level + CHECK (isolation_level IS NULL OR (LOWER(isolation_level) IN ('serializable', 'repeatable read'))); + CREATE SEQUENCE bucardo.customcode_id_seq; CREATE TABLE bucardo.customcode ( id INTEGER NOT NULL DEFAULT nextval('customcode_id_seq'),