## 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();
$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);
}
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
};
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({
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 = ?";
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 {
=item C<name>
-The name of the sync.
+The name of the sync. Required.
=item C<dbs>
Number of times a KID may be kicked before being reaped.
+=item C<isolation_level>
+
+The transation isolation level this sync should use.
+Only choices are "serializable" and "repeatable read"
+
=item C<conflict_strategy>
The conflict resolution strategy to use in the sync. Supported values:
Regex to make sure we don't accidentally run where we should not. Default: None.
+=item C<isolation_level>
+
+The transaction isolation level all sync should use. Defaults to 'serializable'.
+The only other valid option is 'repeatable read'
+
=item C<kid_deadlock_sleep>
How long to sleep in seconds if we hit a deadlock error. Default: C<0.5>.
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
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$$;
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'),