我们需要在Master和Slave MySQL数据库之间拥有相同的用户集,但是希望阻止只读用户连接到Master DB以及防止读写用户连接到从DB。因此,我正在编写一个Login触发器,以防止某些用户根据下表连接到MySql DB:
create table deny_login(user varchar(20),SLAVE_RUNNING varchar(3),deny varchar(1));
我使用“SLAVE_RUNNING”列来解释如何从触发器中区分主数据库和从属数据库。
触发器有效但会话未正确终止。它断开但尝试重新连接等。是否有更简洁的方法从触发器中退出当前会话?
这是表格内容以及触发器定义:
insert into deny_login values ('vlad','OFF', 'n');
insert into deny_login values ('joe','OFF','y');
insert into deny_login values ('vlad@localhost','OFF', 'n');
insert into deny_login values ('joe@localhost','OFF','y');
insert into deny_login values ('joe@localhost','ON','n');
create table test (user varchar(20), deny integer, connection integer);
grant insert, update,delete on test to vlad;
grant insert, update,delete on test to joe;
grant insert, update,delete on test to bill;
grant insert, update,delete on deny_login to vlad;
grant insert, update,delete on deny_login to joe;
grant insert, update,delete on deny_login to bill;
DROP PROCEDURE IF EXISTS login_trigger;
DELIMITER //
CREATE PROCEDURE login_trigger()
SQL SECURITY DEFINER
BEGIN
declare denied integer;
select count(*) into denied from test.deny_login p, information_schema.global_status s where p.user=user() and user not
like '%root%' and s.variable_name='SLAVE_RUNNING' and s.variable_value=p.SLAVE_RUNNING and deny='y';
insert into test values (user(),denied,connection_id());
commit;
if denied = 1 then
-- signal sqlstate '45000' set message_text = 'forbidden';
-- kill( connection_id());
call Fail('forbidden');
end if;
END;
//
DELIMITER ;
REVOKE EXECUTE ON PROCEDURE test.login_trigger FROM 'vlad'@'%';
GRANT EXECUTE ON PROCEDURE test.login_trigger TO 'vlad'@'%';
REVOKE EXECUTE ON PROCEDURE test.login_trigger FROM 'joe'@'%';
GRANT EXECUTE ON PROCEDURE test.login_trigger TO 'joe'@'%';
REVOKE EXECUTE ON PROCEDURE test.login_trigger FROM 'bill'@'%';
GRANT EXECUTE ON PROCEDURE test.login_trigger TO 'bill'@'%';
SET GLOBAL init_connect="";
SET GLOBAL init_connect="CALL test.login_trigger()";
答案 0 :(得分:0)
在奴隶上,SET GLOBAL READ_ONLY = 1;
。然后,具有写权限的用户将无法写入从属设备...任何更改数据的尝试都将遇到错误,该错误基本上表示“从属设备以只读模式运行”并且写入将是拒绝。
具有SUPER
权限的用户将保留写访问权限(但无论如何都不受init_connect
的影响),复制线程也不会受到影响。
对于不需要访问主服务器的用户,从主服务器中删除他们的帐户并将其直接添加到从服务器。只要您不随后将同一用户添加回主服务器而不先将其从服务器中删除,这不会导致问题。
如果客户端尝试自行重新连接,那么没有更优雅的方式来执行您正在尝试的操作。你正在做一个干净的断开连接。我能想到的唯一替代方案是尝试,而不是杀死连接,可能会在过程中放置ROLLBACK RELEASE;
,这也会丢弃客户端连接......虽然我怀疑客户端仍会尝试重新连接,如果客户端意外断开连接。
https://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html#sysvar_read_only
顺便提一下,在当前的实现中,区分主服务器和从服务器的更简单方法是检查@@SERVER_ID
或@@HOSTNAME
变量的值。