定,可以尝试分析一下。如果以这种逻辑,使用binlog-ignore-db=ugly筛选时,第三条语句到底要不要写入日志呢?
为了避免在执行可能被过滤的语句时发生错误,请不要编写那种表名,函数名或存储过程名前面加数据库名的语句,而是通过使用use来改变当前数据库。
还有一个需要说明的是,只要设置了binlog-do-db,过滤器会无视binlog-ignore-db的设置。
当然对于MySQL复制来说,本身不建议使用过滤器,因为日志是不完整的。
二进制日志和安全
一般来说,一个有REPLICATION SLAVE权限的用户拥有读取Master上发生的所有事件的权限,因此为了安全应该保护该账户不被损害。具体预防的措施有:
- 尽可能使从防火墙外无法登录该账户
- 记录所有试图登录到该账户的日志,并将日志放置在一个单独的安全服务器上
- 加密Master和Slave间所用的连接,例如MySQL的built-in SLL
- 敏感信息不要放入日志文件中,比如说密码
# 第二种做法不会把明文密码写入到日志中,更安全些
UPDATE employee SET pass = PASSWORD('foobar')
SET @pass = PASSWORD('foobar');
UPDATE employee SET pass = @pass
触发器
为了在服务器上重放二进制日志,毫无问题的处理各种表的权限,有必要用SUPER权限的用户执行所有语句。但触发器没有被定义使用SUPER权限,所以重要的是以正确的用户作为触发器的定义者去重新创建触发器。CREATE TRIGGER提供了一个DEFINER子句,如果没有给语句指定DEFINER,该语句添加DEFINER子句后被写到二进制日志中,且使用当前用户作为其定义者。
master>SHOW BINLOG EVENTS FROM 92236 LIMIT 1\G
******************** 1. row ********************
Log_name: master-bin.000038
Pos: 92236
Event_type: Query
Server_id: 1
End_log_pos: 92491
Info: use `test`; CREATE DEFINER=`root`@`localhost` TRIGGER ...
调用触发器的语句被记录到二进制日志,但它没有连接到特定的触发器。相反,当Slave执行该语句时,它会自动执行受该语句影响的表相关联的所有触发器,这意味着可以在Master和Slave上有不同的触发器。
存储过程
存储过程的定义语句的处理和触发器是类似的,CREATE PROCETURE语句也有可选的子语句DEFINER,写入二进制日志的时候,会强制加上该子句的。调用过程和触发器不一样。
# 定义存储过程
delimiter $$
CREATE PROCEDURE employee_add(p_name CHAR(64), p_email CHAR(64), p_password CHAR(64))
MODIFIES SQL DATA
BEGIN
DECLARE pass CHAR(64);
set pass = PASSWORD(p_pass)
INSERT INTO employee(name, email, password) VALUES (p_name, p_email, pass);
END $$
delimiter ;
# 调用存储过程
master> CALL employee_add('chunk', 'chuck@example.com', 'abrakadabra');
master> SHOW BINLOG EVENTS FROM 104033\G
******************** 1. row ********************
Log_name: master-bin.000038
Pos: 104033
Event_type: Intvar
Server_id: 1
End_log_pos: 104061
Info: INSERT_ID=1
******************** 2. row ********************
Log_name: master-bin.000038
Pos: 104061
Event_type: Query
Server_id: 1
End_log_pos: 104416
Info: use `test`; INSERT INTO employee(name, email, password) VALUES(
NAME_CONST('p_name',_latin1'chuck' COLLATE 'latin1_swedish_ci'),
NAME_CONST('p_email',_latin1'chuck@example.com' COLLATE 'latin1_swedish_ci'),
NAME_CONST('pass',_latin1'*FEB778934FDSFQOPL7...' COLLATE 'latin1_swedish_ci'))
有四点需要注意:
CALL语句没有被写入二进制日志。取而代之的是,执行语句作为调用的结果被写入二进制日志。
该语句改写为不包含任何对存储过程的参数的引用。取而代之的是,使用NAME_CONST函数为每个参数创建一个单值的结果集
局部声明的变量pass也被换成了NAME_CONST表达式
调用语句写入二进制日志之前,上下文信息已经写入日志,这里指Intvar事件
存储函数
存储过程的定义语句的处理和触发器是类似的,CREATE FUNCTION语句也有可选的子语句DEFINER,写入二进制日志的时候,会强制加上该子句的。调用的时候,存储函数以与触发器相同的方式被复制。有一点需要注意的就是,SELECT语句不会被写入二进制日志,但是一个含有存储函数的SELECT语句是个例外。
对于存储函数还有一个需要提到的是权限问题。CREATE ROUTINE权限是定义一个存储过程或存储函数所必需的。严格说创建一个存储程序不需要其他权限,但它通常根据定义者的权限执行。在Slave上的复制线程在不进行权限检查的情况下执行,这留下了严重的安全漏洞。MySQL 5.0之前的版本没有存储程序,这样不会有问题,因为在Master上违规的语句不会写到二进制日志中。由于存储过程被展开了,只有在Master上成功执行的语句才会写进二进制日志,所以也不会有问题。而存储函数有点不同,它并没有被展开,也就是说有可能在Master和Slave上执行不同的程序分支,带来潜在安全漏洞。在存储函数定义时使用SQL SECURITY DEFINER而不是SQL SECURITY INVOKER可以防止这一点。因为这一点的考虑,MySQL默认要求SUPER权限来定义存储函数。
Events
定义跟其他存储程序一样,也会有DEFINER子句。由于事件由事件调度器调用,因此它们总是以定义者执行从而