原文:http://book.51cto.com/art/200906/132509.htm
1. 引入分布式事务的问题
一旦数据进行切分被分别存放在多个 MySQL Server
中,不管切分规则设计得多么完美(实际上并不存在完美的切分规则),都可能造成之前某些事务所涉及的数据已经不在同一个 MySQL
Server 中了。
在这样的场景下,如果应用程序仍然按照老的方案,那么势必须要引入分布式事务来解决。而在 MySQL 各个版本中,只有从 MySQL
5.0 开始以后的各个版本才对分布式事务提供支持,而且目前仅有 Innodb
提供分布式事务支持。不过,即使我们刚好使用了支持分布式事务的 MySQL 版本,同时也使用 Innodb
存储引擎,分布式事务本身对于系统资源的消耗就很大,性能也并不太高,引入分布式事务在异常处理方面会带来很多比较难控制的问题。
怎么办?其实可以通过一个变通的方法来解决这种问题,首先须要考虑的是:数据库是否是唯一一个能够解决事务的地方?其实并不是这样的,完全可以结合数据库及应用程序来共同解决。各个数据库解决自身的事务,然后通过应用程序来控制多个数据库上的事务。
也就是说,只要我们愿意,完全可以将一个跨多个数据库的分布式事务分拆成多个仅处于单个数据库上的小事务,并通过应用程序来总控各个小事务。当然,这样做要求应用程序必须要有足够的健壮性,当然也会给应用程序带来一些技术难度。
2. 跨节点 Join 的问题
上面介绍了可能引入分布式事务的问题,现在再看看需要跨节点 Join 的问题。数据切分之后,也许有些老的 Join
语句无法继续使用,因为 Join 使用的数据源可能被切分到多个 MySQL Server 中了。
怎么办?这个问题从 MySQL 数据库角度来看,如果非得在数据库端直接解决的话,恐怕只能通过 MySQL 一种特殊的存储引擎
Federated 处理了。Federated 存储引擎是 MySQL 解决类似于 Oracle 的 DB Link
之类问题的方案。和 Oracle DB Link 的主要区别在于,Federated
会保存一份远端表结构的定义信息在本地。乍一看,Federated 确实是解决跨节点 Join
非常好的方案。但是我们还应该清楚一点,那就是如果远端的表结构发生了变更,本地的表定义信息是不会跟着发生变化的。如果在更新远端表结构的时候并没有更新本地的
Federated 表定义信息,Query 运行很可能出错,无法得到正确的结果。
对待这类问题,还是推荐通过应用程序来处理,先在驱动表所在的 MySQL Server
中取出驱动结果集,然后根据驱动结果集再到被驱动表所在的 MySQL Server
中取出相应的数据。可能很多读者朋友会认为这样做将对性能产生一定的影响,是的,确实会有一定的负面影响,但除此之外,基本上没有太多其他更好的解决办法了。而且,由于数据库通过较好的扩展之后,每台
MySQL Server 的负载就可以得到较好的控制,单纯针对单条 Query
来说,其响应时间可能比不切分之前要提高一些,所以性能方面带来的负面影响也并不是太大。更何况,类似于这种跨节点 Join
的需求也并不是太多,相对于总体性能而言,可能也只是很小一部分而已。所以为了整体性能,偶尔牺牲一点点,其实是值得的,毕竟系统优化本身就是很多取舍和平衡的过程。
3. 跨节点合并排序分页问题
一旦进行了数据的水平切分之后,可能就并不只有跨节点 Join 无法正常运行,有些排序分页的 Query
语句的数据源可能也会被切分到多个节点,其直接后果就是这些排序分页 Query 无法继续正常运行。其实这和跨节点 Join
是一个道理,数据源存在于多个节点上,要通过一个 Query 来解决,就是一个跨节点 Join 操作。同样 Federated
也可以部分解决,但存在的风险也一样。但是有一点不同:Join
很多时候都有一个驱动与被驱动的关系,所以它涉及的多个表之间的数据读取一般会存在一个顺序关系。但是排序分页就不同了,排序分页的数据源基本上可以说是一个表(或者一个结果集),并不存在顺序关系,所以从多个数据源取数据的过程是完全可以并行的。这样,排序分页数据的取数效率可以比跨库
Join 更高,所以带来的性能损失相对要小,在有些情况下可能比在原来未进行数据切分的数据库中效率更高了。当然,不论是跨节点 Join
还是跨节点排序分页,都会使应用服务器消耗更多的资源,尤其是内存资源,因为在读取访问及合并结果集的这个过程须要比不处理合并处理更多的数据。
分析到这里,可能很多读者朋友会发现,上面所有的这些问题,我的建议基本上都是通过应用程序来解决的。大家可能心里开始犯嘀咕了,是不是因为我是
DBA,所以就把很多事情都扔给应用架构师和开发人员了?
其实完全不是这样,首先应用程序由于其特殊性,可以非常容易做到很好的扩展性,但是数据库就不一样,必须借助很多其他的方式才能做到扩展,而且在扩展过程中,很难避免带来有些原来在集中式数据库中可以解决但被切分开成一个数据库集群之后就成为一个难题的情况。要想让系统整体得到最大限度的扩展,只能让应用程序做更多的事情,来解决数据库集群无法较好解决的问题。
青春就应该这样绽放 游戏测试:三国时期谁是你最好的兄弟!! 你不得不信的星座秘密