mysql-master-haでのREPLICATION SLAVE priv.チェックの修正
mysql-master-haでのREPLICATION SLAVE priv.チェックの修正
mysql-master-haをちょっと触っていたところ、MHAの管理ユーザーがmysql.userテーブルをSELECTしていたのがちょっと気持ち悪かったので修正してみました:
--- lib/MHA/Server.pm.old 2012-01-09 00:06:53.000000000 +0900 +++ lib/MHA/Server.pm 2012-05-17 18:34:30.000000000 +0900 @@ -377,7 +377,7 @@ $log = $self->{logger} unless ($log); if ( !$self->{no_master} && $self->{log_bin} && !$self->{not_slave} ) { my $dbhelper = $self->{dbhelper}; - unless ( $dbhelper->has_repl_priv( $self->{repl_user} ) ) { + unless ( $dbhelper->has_repl_priv( $self->{repl_user}, $self->{repl_password}, $self->{hostname}, $self->{port} ) ) { $log->error( sprintf( "%s: User %s does not exist or does not have REPLICATION SLAVE privilege! Other slaves can not start replication from this host.", --- lib/MHA/DBHelper.pm.old 2012-01-09 00:06:43.000000000 +0900 +++ lib/MHA/DBHelper.pm 2012-05-17 18:33:15.000000000 +0900 @@ -103,6 +103,7 @@ use constant Unlock_Tables_SQL => "UNLOCK TABLES"; use constant Repl_User_SQL => "SELECT Repl_slave_priv AS Value FROM mysql.user WHERE user = ?"; +use constant Show_Grants_SQL => "SHOW GRANTS"; sub new { my $class = shift; @@ -218,17 +219,26 @@ sub has_repl_priv { my $self = shift; my $user = shift; - my $sth = $self->{dbh}->prepare(Repl_User_SQL); - my $ret = $sth->execute($user); - if ( !defined($ret) ) { + my $password = shift; + my $host = shift; + my $port = shift; + + my $res = eval { + my $dbh = connect_util( $host, $port, $user, $password ); + my $sth = $dbh->prepare(Show_Grants_SQL); + $sth->execute() or die; + my $values = $sth->fetchrow_arrayref; + foreach my $value (@$values) { + return 1 if $value =~ /\WREPLICATION SLAVE\W/; + } + return 0; + }; + if ($@) { croak "Got MySQL error when checking replication privilege. $DBI::err: $DBI::errstr query:" - . Repl_User_SQL . "\n"; + . Show_Grants_SQL . "\n"; } - my $href = $sth->fetchrow_hashref; - my $value = $href->{Value}; - return 1 if ( defined($value) && $value eq "Y" ); - return 0; + return $res; } sub is_binlog_enabled($) {
repl_userで接続してSHOW GRANTSすれば権限を確認できるはず、ということで上記のような修正になっています。
この修正をした場合はconfigにrepl_passwordが必須になると思います*1。
mha管理ユーザーで必要な権限
GRANT RELOAD, PROCESS, SUPER, REPLICATION CLIENT ON *.* TO 'mha';
――でいいのかな?
*1:repl_userにパスワードを設定している場合は。……あれ、通常でも必須なんだっけ?