如果我们只需要将数据库中的部分表复制到从数据库上,那么可以通过replicate-do-db、replicate-do-table、replicate-ignore-db、replicate-ignore-table、replicate-wild-do-table复制选项来选择只需要复制的表或者数据库。
但是这几个参数只是将符合条件的表或者数据库的binlog apply到从数据库中,不能过滤传输的binlog的内容。如果我们需要复制的内容很少,而不需要复制的内容很多的时候,就会无谓在主从服务器之间传输很多不需要的binlog,这种情况下,我们可以通过使用blockhole存储引擎过滤需要的binlog,而又不会对主数据库造成太大的额外的压力。
blockhole,直译就是黑洞的意思,使用这个存储引擎的表,不论执行什么操作,都不会实际像表中插入记录,但是对这个表的更新操作,却可以通过binlog记录下来。
下面我们测试使用blockhole进行binlog过滤得步骤:
首先要创建一个正确的主从复制环境,最好在相同服务器上创建,这样才能达到减少网络传输的问题。
我们在test用户下面有两个表:
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| test_myisam |
| test_myisam1 |
+----------------+
2 rows in set (0.00 sec)
我们对这两个表的更新,都会记录到binlog中,并且都会传输到从服务器上执行。
主数据库执行:
mysql> insert into test_myisam1 values(1,'ttt'),(2,'aaa');
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
从数据库:
mysql> select * from test_myisam1;
+------+------+
| i | c |
+------+------+
| 1 | ttt |
| 2 | aaa |
+------+------+
2 rows in set (0.00 sec)
我们在从服务器上设置replicate-do-table=test.test_myisam,只复制其中的一个表,并且打开从数据库的log-slave-updates,确保从数据库的更新可以写binlog,然后重启从数据库生效。
启动后,更新两个表的记录,只有test_myisam地更新执行到从数据库中,但是传输到从数据库的binlog包括全部的更新信息。
主数据库:
mysql> insert into test_myisam1 values(1,'ttt'),(2,'aaa');
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> insert into test_myisam values(1,'ttt'),(2,'aaa');
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from test_myisam;
+------+------+
| i | c |
+------+------+
| 1 | ttt |
| 2 | aaa |
+------+------+
2 rows in set (0.00 sec)
mysql> select * from test_myisam1;
+------+------+
| i | c |
+------+------+
| 1 | ttt |
| 2 | aaa |
| 1 | ttt |
| 2 | aaa |
+------+------+
4 rows in set (0.00 sec)
从数据库:
mysql> select * from test_myisam;
+------+------+
| i | c |
+------+------+
| 1 | ttt |
| 2 | aaa |
+------+------+
2 rows in set (0.00 sec)
mysql> select * from test_myisam1;
+------+------+
| i | c |
+------+------+
| 1 | ttt |
| 2 | aaa |
+------+------+
2 rows in set (0.00 sec)
下面是传输到从数据库的binlog:
[lisa1@localhost data]$ mysqlbinlog localhost-relay-bin.000007
......
/*!C gbk *//*!*/;
SET @@session.character_set_client=28,@@session.collation_connection=28,@@session.collation_server=8/*!*/;
insert into test_myisam1 values(1,'ttt'),(2,'aaa')/*!*/;
# at 348
#070807 16:15:12 server id 1 end_log_pos 900 Query thread_id=9 exec_time=0 error_code=0
SET TIMESTAMP=1186474512/*!*/;
insert into test_myisam values(1,'ttt'),(2,'aaa')/*!*/;
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
下面是从数据库执行更新写的binlog:
[lisa1@localhost data]$ mysqlbinlog mysql-bin.000004
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#070807 16:15:01 server id 2 end_log_pos 98 Start: binlog v 4, server v 5.0.45-log created 070807 16:15:01 at startup
# Warning: this binlog was not closed properly. Most probably mysqld crashed writing it.
ROLLBACK/*!*/;
# at 98
#070807 16:15:12 server id 1 end_log_pos 210 Query thread_id=9 exec_time=0 error_code=0
use test/*!*/;
SET TIMESTAMP=1186474512/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1/*!*/;
SET @@session.sql_mode=0/*!*/;
/*!C gbk *//*!*/;
SET @@session.character_set_client=28,@@session.collation_connection=28,@@session.collation_server=8/*!*/;
insert into test_myisam values(1,'ttt'),(2,'aaa')/*!*/;
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
从两个binlog可以看出,已经有效的过滤了binlog的内容,只保留了我们关心的test_myisam表的更新信息。
最后,我们把从数据库上test_myisam表的存储引擎修改成blockhole的,这样对从数据库的访问压力降低到最小,只是简单的进行binlog的过滤。
从数据库:
mysql> alter table test_myisam engine=blackhole;
Query OK, 2 rows affected (0.03 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from test_myisam;
Empty set (0.00 sec)
然后在主数据库上进行更新操作:
mysql> insert into test_myisam values(3,'bbb'),(4,'ccc');
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from test_myisam;
+------+------+
| i | c |
+------+------+
| 1 | ttt |
| 2 | aaa |
| 3 | bbb |
| 4 | ccc |
+------+------+
4 rows in set (0.00 sec)
从数据库:
mysql> select * from test_myisam;
Empty set (0.00 sec)
检查从数据库写的binlog:
[lisa1@localhost data]$ mysqlbinlog mysql-bin.000004
......
SET @@session.character_set_client=28,@@session.collation_connection=28,@@session.collation_server=8/*!*/;
insert into test_myisam values(1,'ttt'),(2,'aaa')/*!*/;
# at 210
#070807 16:17:09 server id 2 end_log_pos 313 Query thread_id=4 exec_time=0 error_code=0
SET TIMESTAMP=1186474629/*!*/;
/*!C latin1 *//*!*/;
SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/;
alter table test_myisam engine=blackhole/*!*/;
# at 313
#070807 16:17:41 server id 1 end_log_pos 425 Query thread_id=9 exec_time=0 error_code=0
SET TIMESTAMP=1186474661/*!*/;
/*!C gbk *//*!*/;
SET @@session.character_set_client=28,@@session.collation_connection=28,@@session.collation_server=8/*!*/;
insert into test_myisam values(3,'bbb'),(4,'ccc')/*!*/;
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
可以发现,更新操作虽然没有实际写到从数据库的表中,但是更新的操作正确记录在binlog中。
注意事项:
由于blockhole表中并没有实际的记录,所以,对blockhole表的insert触发器可以触发,但是update和delete触发器都不会触发。
这样,如果在主数据库上的表有update和delete触发器,就不能使用blockhole存储引擎进行binlog过滤,因为触发器的操作并没有写在binlog中,
而是需要通过主表的更新来触发从数据库的触发器的,如果从数据库的触发器不能触发,那么数据就不同步了。
mysql> CREATE TABLE IF NOT EXISTS test_father ( id smallint(5) unsigned NOT NULL AUTO_INCREMENT, note varchar(10) NOT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB;
Query OK, 0 rows affected (0.10 sec)
mysql> create table test_sun(id int AUTO_INCREMENT,note varchar(20),PRIMARY KEY (id));
Query OK, 0 rows affected (0.05 sec)
mysql> DELIMITER $$
mysql> CREATE TRIGGER ins_test_father_bef
-> BEFORE INSERT ON test_father FOR EACH ROW BEGIN
-> INSERT INTO test_sun (note) VALUES (new.note);
-> END;
-> $$
Query OK, 0 rows affected (0.00 sec)
mysql> delimiter ;
mysql> insert into test_father values(1,'abcd');
Query OK, 1 row affected (0.11 sec)
mysql> select * from test_sun;
+----+------+
| id | note |
+----+------+
| 1 | abcd |
+----+------+
1 row in set (0.00 sec)
察看传输到从数据库的binlog:
[lisa1@localhost data]$ mysqlbinlog localhost-relay-bin.000013
......
#070807 17:07:25 server id 1 end_log_pos 103 Query thread_id=9 exec_time=0 error_code=0
SET TIMESTAMP=1186477645/*!*/;
insert into test_father values(1,'abcd')/*!*/;
# at 784
#070807 17:07:25 server id 1 end_log_pos 3946 Xid = 82
COMMIT/*!*/;
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
其他blockhole的可能用途可以用来对比是否打开binlog对数据库性能的影响程度,或者测试数据库和存储引擎不相关的性能瓶颈。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/51862/viewspace-180656/ ,如需转载,请注明出处,否则将追究法律责任。