You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
proxysql/tools/proxysql_galera_writer.pl

100 lines
3.5 KiB

#!/usr/bin/perl
use strict;
use warnings;
use vars;
use DBI;
use DBD::mysql;
## CUSTOMIZE THESE CONSTANTS
use constant {
HOST => "127.0.0.1",
PORT => "6032",
USER => "admin",
PASS => "admin",
VERB => 1
};
our $dbn;
our $dbh;
sub main {
@ARGV = @_;
my $nargs=$#ARGV + 1;
if ($nargs != 3) {
print STDERR "Incorrect number of arguments\n";
return 1;
}
my $writerHG=$ARGV[0];
my $readerHG=$ARGV[1];
my $maxwriters=$ARGV[2];
if (VERB) {
print STDERR "Writer hostgroup: $writerHG\n";
print STDERR "Reader hostgroup: $readerHG\n";
print STDERR "Max num writers: $maxwriters\n";
}
# connect to Admin interface and retrieve the current ative masters
$dbn="dbi:mysql:main:".HOST.":".PORT;
$dbh=DBI->connect($dbn, USER, PASS) or die "Unable to connect: $DBI::errstr\n";
my $selh=$dbh->prepare("SELECT hostname,port FROM runtime_mysql_servers WHERE status='ONLINE' AND hostgroup_id=$writerHG") or die "Unable to prepare: $DBI::errstr\n";
$selh->execute() or die "Unable to execute: $DBI::errstr\n";
my @data;
while (my $res=$selh->fetchrow_hashref) {
push (@data, $res);
}
my $active_writers= scalar @data;
if (VERB) {
print STDERR "Active writers found: $active_writers\n";
foreach (@data) {
my $s=$_;
print " $s->{'hostname'} $s->{'port'}\n";
}
}
if ($active_writers==$maxwriters) {
if (VERB) {
print STDERR "Active writers match max number of writers: exit with no action\n";
}
return 0;
}
# if the execution of the script reaches here, some action is required
if (VERB) {
print STDERR "$active_writers active writers found do not match $maxwriters writers expected\n";
}
# although we run the check on runtime_mysql_servers , we will perform all the operations on mysql_servers
# be aware that in ProxySQL Admin doesn't support locking or transactions, so, even if unlikely,
# it is possible that race conditions can happen if two scripts update mysql_servers at the same
# first, set to OFFLINE_SOFT all nodes in the writer hostgroup
# OFFLINE_SOFT doesn't terminate current transactions, therefore it is a graceful "shutdown"
print STDERR "Disabling old $active_writers write(s)\n";
$dbh->do("UPDATE mysql_servers SET status='OFFLINE_SOFT' WHERE hostgroup_id=$writerHG") or die "Unable to set writes offline: $DBI::errstr\n";
# here we define the new masters
# the algorithm used to determine the new masters is customizable: define the algorithm you prefer
# CUSTOMIZE IT!
print STDERR "Adding new $maxwriters write(s)\n";
# in this example, the algorithm is that are promoted as master(s) the first N hosts order by ORDER BY weight DESC, hostname, port
$dbh->do("REPLACE INTO mysql_servers (hostgroup_id, hostname, port, status, weight, max_connections, use_ssl) SELECT $writerHG , hostname, port, status, weight, max_connections, use_ssl FROM mysql_servers WHERE hostgroup_id=$readerHG AND status='ONLINE' ORDER BY weight DESC, hostname, port LIMIT $maxwriters") or die "Unable to set new writer: $DBI::errstr\n";
# now we load at RUNTIME
print STDERR "Loading to runtime...";
$dbh->do("LOAD MYSQL SERVERS TO RUNTIME") or die "Unable to LOAD MYSQL SERVERS TO RUNTIME: $DBI::errstr\n";
print STDERR " Done!\n";
# as last step, we display the current masters
print STDERR "Reporting new writer(s) :\n";
$selh->execute() or die "Unable to execute: $DBI::errstr\n";
my @newhosts;
while (my $res=$selh->fetchrow_hashref) {
push (@newhosts, $res);
}
foreach (@newhosts) {
my $s=$_;
print " $s->{'hostname'} $s->{'port'}\n";
}
return 0;
}
if(!caller) { exit(main(@ARGV)); }