MySQL分库分表方案
MySQL分库分表方案
翻译一个stackoverflow上的答案,关于分库分表的缺点的,原文链接: https://stackoverflow.com/questions/5541421/mysql-sharding-approaches
问题:
什么是最好的切分MySQL表的方式?我想到的有:
- 应用层切分?
- MySQL代理层切分?
- 提供中心查找分片服务?
你们知道任何这方面有趣的项目或者工具吗?
回答:
最好的切分MySQL的方式就是:除非万不得已,不要去干它。
当你写一个应用的时候,你通常都想要最快的开发速度。 只有当需要时,你才开始优化延时,提高吞吐量,
你切分数据库的原因无非因为数据库的读或者写: 数据库写:写操作永久的超过了服务器的磁盘负载;太多写入导致副本同步永远的落后了。 数据库读:读取到的数据量太大以至于称爆内存;并且大多数读操作开始直击磁盘而不是从内存中读取数据。
只有这时,你才需要做数据库切分。
当你开始切分后,你开始以以下几种方式支付代价:
你的SQL语句不再是声明式的(declarative)
一般的,你用SQL语句告诉数据库你要什么数据,然后让优化器优化SQL并转化成数据获取程序。 这很棒,因为它非常灵活,而且写这些转化程序很无聊,严重影响开发速度。
分布式环境下,你将A节点的表和B节点的表进行join,甚至有些表的数据大到超过一个节点, 在A节点和B节点将数据join起来,然后和B节点和C节点join的数据聚合。 你开始写单方面的hash应用程序来解决这个问题(或者你可以再造MySQL的集群), 这表示结果你得到一大堆的非声明式的SQL,而且让它以一种面向过程的方式工作。
你招致了大量的网络延时
一般的,一条SQL查询语句可以本地解决并且优化器知道在本地磁盘的消耗时间, 可以最小的消耗解决这个查询问题。
在分布式环境下,查询语句必须要通过KV映射,访问多个网络节点(希望是批量访问, 而不是每个Key一次往返),或者将WHERE条件放在他们将被执行的节点上。
但是即使在最好的情况下,涉及到许多网络往返都会更加复杂。特别是MySQL的优化器完全 不知道网络延时的情况。
你时区了SQL的许多强大能力
好吧,这或许没那么重要,但是外检约束,其他保证数据完整性的SQL机制,对于跨多个节点 是无能为力的。
MySQL没有API保证异步查询顺序工作
当相同类型的数据存放在多个节点上(比如用户数据存放在A,B,C节点上),水平查询 需要访问所有节点,数据访问时间直接因以节点数线性增长。除非多个节点是已并行方式 访问,然后在以Map-Reduce的方式聚合。
前提是需要异步通信的API,单这并不存在于MySQL很好的工作态。可选的方案是 在子进程中增加很多的forking和连接,
总结
当你开始切分,数据结构和网络拓扑明显影响到应用的性能。为了运行良好,你的应用 需要当心这些事情,这表明只有应用层的切分才有意义。
如果需要自动切分,问题会更多(比如决定那个节点的那个列作为hash主键),或者 你想要手动进行切分,xyz用户去这个主库上,abc去和def去到那个主库上。
业务功能上的切分有些好处,如果做对了,这对绝大部分开发人员是透明的。因为所有相关 的表都存放在本地。折让透明从声明式的SQL中尽量受益,并且有更少的网络延时,因为 跨节点的网络访问被保持到最小化。
业务功能上的切分的缺点是,它不能准许单个表的数据膨胀过大,这需要设计者的主动注意。
业务功能切分的好处是,针对一个并没有太多改变的代码库,它相对而言非常简单。 Booking.com在过去几年进行过几次,并且能很好的工作。