OneProxy :: 增加Spring框架readonly=true事务的读写分离支持,无须更改应用!

在Spring框架中有三种事务模板:读写事务、只读事务和非事务。在绝大多数现有应用程序中,没有加以严格区分,一般都将所有的SQL放到读写事务中执行,这种情况下,很难利用中间件来实现透明的读写分离,这个很难不是技术上的原因,而是业务上的原因。少部份应用为了通过MySQL JDBC自带的读写分离功能,将查询语句放到只读事务中,这种情况下中间件可以很好地实现读写分离,将只读事务中的SQL语句路由到备库是完全可以的。极少量的应用在编写时,充分考虑到了架构的扩展,将不需要事务的SQL放在非事务模板中执行,让中间件极易处理。

OneProxy中间件,针对全部SQL放在读写事务中的模式,设计了Lazy Transaction模式,可以延迟事务的发生到事务中的第一个DML语句时才发生,也就是将事务中的查询语句透明地提取出来,放到事务外执行,以实现读写分离。从技术上只需要设置如下参数:

......
proxy-lazy-transaction       = 1
......

这个情况下,业务能否接受此种模式的读写分离是关键。即使不是Spring程序,比如在会话级别将“autocommit”设置成0,也会将所有的SQL放到事务中执行。也遇到过应用程序的连接池中,“autocommit”设置混乱的情况,即连接池中有的连接此属性值为0,有的连接此属性为1,引起应用程序事务管理异常。

为了适应客户端连接池管理混乱的情况,OneProxy可以通过设置重置“autocommit”选项,在事务结束后,将“autocommit”的属性强制还原为1。如下所示:

......
proxy-reset-autocommit       = 1
......

对于Spring程序中的只读事务,OneProxy可以将只读事务忽略掉,将只读事务变为一条一条离散的SQL语句来执行,只需要在OneProxy的配置文件中设置以下参数:

......
proxy-ignore-readonly       = 1
......

当应用程序发送只读事务过来时,OneProxy将不会真正开启只读事务,而是直接跳过事务开起命令,让只读事务内的SQL以非事务方式执行,从而可以路由到不同的备库执行,透明实现读写分离。通过这三个选项,可以在技术上为不同类型应用的透明读写分离扫清障碍,当然最好的办法还是应用程序中严格区分事务模板,OneProxy的事务监控功能,可以帮你迅速那些只有查询语句的事务,进行级有针对性的应用调整。