From 4b4e1234a188c517964f38b40be8332952099545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Tue, 19 Jul 2016 13:39:51 +0000 Subject: [PATCH] Added tool proxysql_galera_writer.pl --- tools/proxysql_galera_writer.pl | 99 +++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 tools/proxysql_galera_writer.pl diff --git a/tools/proxysql_galera_writer.pl b/tools/proxysql_galera_writer.pl new file mode 100644 index 000000000..f94f0d83e --- /dev/null +++ b/tools/proxysql_galera_writer.pl @@ -0,0 +1,99 @@ +#!/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)); }