不会存在存储函数的安全漏洞。当事件被执行时,该语句被直接写入二进制日志。由于事件是在Master上执行的,他们在Slave上是自动禁止的。但有时候如果需要升级Slave,就需要允许在Slave上执行这些事件。
UPDATE mysql.events SET status = ENABLED WHERE status = SLAVESIDE_DISABLED;
特殊结构
尽管基于语句的复制通常是简单的,但一些特殊结构必须小心处理,才能很好的来保证Slave执行语句时的上下文跟Master上执行时是一样的。
LOAD_FILE函数
LOAD_FILE函数让你可以获取一个文件,由于在复制过程中,它不会被传输,所以需要改写。
INSERT INTO document(author, body) VALUES ('Fox', LOAD_FILR('index.html'));
# 可以用LOAD DATA FILE改写
LOAD DATA INFILE 'index.html' INTO TABLE document FIELDS TERMINATED BY '@*@' LINES TERMINATED BY '&%&' (author, body) SET author = 'FOX';
# 还可以用用户定义变量改写
SET @document = LOAD_FILE('index.html');
INSERT INTO document(author, body) VALUES ('Fox', @document);
非事务性的变化和错误处理
如果有一个employee表是支持事务的InnoDB存储引擎(主键是mail),而跟踪employee修改的log表是不支持事务的MyISAM存储引擎。在其上定义两个触发器,一个在INSERT之前触发tr_insert_before,插入一条记录到log表,插入纪录的状态为FAIL;一个在INSERT之后触发tr_insert_after,更改刚才插入纪录的状态为OK。连续插入两条完全相同记录时,tr_insert_before被触发,tr_insert_after则不会被触发。虽然employee失败回滚了,但是log里面插入的数据却没办法回滚,这是个问题。执行后二进制日志文件内容如下。
master> SET @pass = PASSWORD('xyz');
master> INSERT INTO employee (name, mail, password) VALUES ('hu', 'hu@fox.com', @pass);
master> INSERT INTO employee (name, mail, password) VALUES ('hu', 'hu@fox.com', @pass);
master> SHOW BINLOG EVENTS IN 'local-bin.000023'
******************** 1. row ********************
Log_name: master-bin.000023
Pos: 1252
Event_type: Query
Server_id: 1
End_log_pos: 1320
Info: use 'test'; BEGIN
******************** 2. row ********************
Log_name: master-bin.000023
Pos: 1320
Event_type: Intvar
Server_id: 1
End_log_pos: 1348
Info: LAST_INSERT_ID=1
******************** 3. row ********************
Log_name: master-bin.000023
Pos: 1348
Event_type: User var
Server_id: 1
End_log_pos: 1426
Info: @'pass'=_utf 0x432423jklfslagklr... COLLATE utf8_general_ci
******************** 4. row ********************
Log_name: master-bin.000023
Pos: 1426
Event_type: Query
Server_id: 1
End_log_pos: 1567
Info: use 'test'; INSERT INTO employee ...
******************** 5. row ********************
Log_name: master-bin.000023
Pos: 1567
Event_type: Xid
Server_id: 1
End_log_pos: 1594
Info: COMMIT /* xid=60 */
******************** 6. row ********************
Log_name: master-bin.000023
Pos: 1594
Event_type: Query
Server_id: 1
End_log_pos: 1662
Info: use 'test'; BEGIN
******************** 7. row ********************
Log_name: master-bin.000023
Pos: 1662
Event_type: Intvar
Server_id: 1
End_log_pos: 1690
Info: LAST_INSERT_ID=1
******************** 8. row ********************
Log_name: master-bin.000023
Pos: 1690
Event_type: User var
Server_id: 1
End_log_pos: 1768
Info: @'pass'=_utf 0x432423jklfslagklr... COLLATE utf8_general_ci
******************** 9. row ********************
Log_name: master-bin.000023
Pos: 1768
Event_type: Query
Server_id: 1
End_log_pos: 1909
Info: use 'test'; INSERT INTO employee ...
******************** 10. row ********************
Log_name: master-bin.000023
Pos: 1909
Event_type: Query
Server_id: 1
End_log_pos: 1980
Info: use 'test'; ROLLBACK
事务
由上面的二进制日志内容可以看到,执行事务的时候需要额外的处理。对于事务来说,为了使得每个事务的所有语句在一起,不是按照事务的开始顺序而是提交顺序记入二进制日志。为了确保每个事务都作为一个单元被写入二进制日志,服务器需要将在不同线程