OneProxy :: 巧用查询重写功能将表透明打散到多个库,顺利开启并行恢复!

在使用MySQL时侯,最头疼的一个问题是如何提升备库Binlog日志回放速度,在MySQL 5.6版本以前,有且只有一个SQL恢复线程,真是一点办法都没有。好在到5.6版本以后,MySQL官方版本和MariaDB分支都提供了一个并行恢复的机制,可以起动多个SQL恢复线程,给了大家一个希望。区别是MariaDB分支通过改造Binlog日志的格式,允许单次组提交里的每个事务并行执行,而官方MySQL版本只能按不同的数据库并行,看似没有那么实用。

只要我们能够将表分到不同的数据库下,就可以启用并行恢复,如果你已经使用OneProxy来做水平分库分表,将超大的表拆分成一个一个小表,可以轻松地将不同的表分到不同的数据库下,不需要升级到MySQL 5.7(刚刚发布没有多久)或切换到不兼容的MariaDB分支(与官方不再兼容)上。关键是对于现有的应用,如何将表透明地均分到不同的数据库里,单纯为了这个目的去改造应用的成本是有点高。由于MySQL本身没有同义词功能,跨库访问时必须要在表名之前加上库名,如下所示:

mysql> show tables;
+----------------------------+
| Tables_in_test             |
+----------------------------+
| oneproxy_replication_check |
+----------------------------+
1 row in set (0.00 sec)

mysql> select count(*) from data01.t_data01;
+----------+
| count(*) |
+----------+
|        1 |
+----------+
1 row in set (0.00 sec)

mysql> select count(*) from t_data01;
ERROR 1146 (42S02): Table 'test.t_data01' doesn't exist

如果访问“t_data01”时不加上数据库名,则会报错;如果在应用程序中硬性地加上,又太不灵活了。这时可以使用OneProxy中间件的同义词功能,来将“t_data01”透明地替换成“data01.t_data01” ,从而避免应用程序的修改,又具有灵活调整的便捷性。下面是增加了同义词参数后的效果,没有看到表,却可以访问。

mysql> show tables;
+----------------------------+
| Tables_in_test             |
+----------------------------+
| oneproxy_replication_check |
+----------------------------+
1 row in set (0.00 sec)

mysql> select count(*) from t_data01;
+----------+
| count(*) |
+----------+
|        1 |
+----------+
1 row in set (0.00 sec)

所做的工作只是将表移到了别的库中,并且在OneProxy的启动参数中增加了一项“proxy-table-synonym”配置。

[oneproxy]
keepalive     = 1
event-threads = 4
log-file      = log/oneproxy.log
pid-file      = log/oneproxy.pid
lck-file      = log/oneproxy.lck
mysql-version		 = 5.6.27
proxy-address            = :3307
proxy-master-addresses.1 = 172.30.12.4:3316@server1
proxy-user-list          = test/1378F6CC3A8E8A43CA388193FBED5405982FBBD3@test
proxy-charset            = gbk_chinese_ci
proxy-group-policy       = server1:master-only
proxy-table-synonym.1	 = t_data01:data01.t_data01

OneProxy会对SQL中的表名进行透明地替换,相当于是查询改写, 来达到应用的透明性。你可以从OneProxy中得到每个表增删改查等不同操作的频率,来平均地将写入压力均分到多个数据库中,然后开启MySQL 5.6中的不同库并行恢复功能,来提升备库的恢复速度,平民软件已经在Zabbix上做过验证。现在你可以多测试一些不同的SQL,看看他们能否正常工作。

mysql> insert into t_data01 values (2,2);
Query OK, 1 row affected (0.02 sec)

mysql> select * from t_data01;
+----+------+
| id | col2 |
+----+------+
|  1 |    1 |
|  2 |    2 |
+----+------+
2 rows in set (0.00 sec)

按库并行功能因为逻辑简单,运行的效率非常之高,要比基于事务组提交的方式性能更高。在MySQL 5.7中,如果对新的并行复制机制不安心的话,也可以编写自己的查询重写插件,但我会偏向于在中间件里实现。在使用OneProxy做分库分表解决方案时,可以在配置文件中为每个分片定义所在的数据库的名字(请注意“db”属性)。

[
   {
        "table"   : "TB_TESTTRACE",
        "pkey"    : "SFBM",
        "type"    : "char",
        "method"  : "hash",
        "partitions":
           [
               { "db":"db01", "suffix" : "_0", "group": "data1" },
               { "db":"db02", "suffix" : "_1", "group": "data1" },
               { "db":"db03", "suffix" : "_2", "group": "data1" },
               { "db":"db04", "suffix" : "_3", "group": "data1" }
	   ]
   }
]

只要用心总能找到良好的解决方案,提升备库恢复速度并不是一件非常困难的事情。