日期:2014-05-16  浏览次数:20837 次

myslq分表分库方案,请大家指正,多谢先!
项目背景:
最近写了一个小程序,对订单数据处理,写入/读取次次差不多,近2月约为30W条数据(mysql存储),且在近一步快速增长中。心里很是紧张,如果超过100W了会如何?

解决问题:数据记录多时读取速度。

在网上搜索了Mysql的分表分库方案,主要有mysql proxy,Amoeba,HiveDB等。大概比较了一番,好象都不能完全达到我的理想要求:
R1.数据库、数据表可以无限增加
R2.增加时进无需要迁移数据,或者简略简单。
R3.可以人工分配
R4.解决日期分段提历史数据查询问题,并可与主库分离(一个业务库对一个历史库2-3年数据,更早期数据归档,用户不能查询)
R5.解决主从数据库的访问,或者单点故障。

可配置,尽量不修改现在的程序。

解决办法:
为每人用户分配一个数据分区标志,终身不变以此定位数据。如user1(分区标志3)则交易数据存存在tblxx_3,历史数据存储在tblxx_3_yyyymm中,tbl_xx是开发测试时使用,也是一个真实的分表。
配置文件定义:
1. tblxx 可被替换
2. 分区标志3的数据库位置信息{3,},实际如下(php代码)
PHP code
$shard['dbservers']=array(
'master'=>array(
            array('1,3,70','localhost', 'eprinter', 'root', 'root', 'mysql'),
            array('2,4,50','localhost', 'eprinter2', 'root', 'root', 'mysql')
        ),
'slave'=>array(
            array('1,3,5','localhost', 'eprinter', 'root', 'root', 'mysql'),
            array('2,4,50','localhost', 'eprinter2', 'root', 'root', 'mysql')
        ),
'history'=>array(
            array('1,3,5','localhost', 'eprinter', 'root', 'root', 'mysql'),
            array('2,4,50','localhost', 'eprinter2', 'root', 'root', 'mysql')
        )
);


3.程序调整地方:
(1)设置用户分区代码(session启动时{user.分区码}写到数据访问类db中) 
(2)拦截SQL,执行简单的SQL替换,将tblxx,替换成tblxx_分区码
(3)根据分区码,选择数据库.(这一步目前未实现,我分了10表,感觉已经够多的了,50W*10,也够我用好长时间了。)

完了!!!

附记:方案想了很久,代码花了半天时间,实际运行了几天,感觉良好。

潜在问题:可能遇到到数据库IO瓶颈(实现3.(1)后可消除),WEB服务单点故障。

结论:也算是一个可管理的分库分表方案,或者数据库透明代理了。

请大家指出不足的地方,以改进。请大家指出不足的地方,以改进。多谢,多谢,多谢!!!






------解决方案--------------------
100W,弱爆了!
------解决方案--------------------
mssql的分区,对于sql是透明的

有一个每年增1亿条记录的表,分了100个区,目前2.3亿条记录了,还一切正常
------解决方案--------------------
java写个简单的路由表的规则就可以了
代码改动不太大,就可以实现分库,分表。
------解决方案--------------------
根据某一个字段的某种规则分表或者分库
然后根据这个规则写代码计算这条数据应该放到哪个库的哪个表里
------解决方案--------------------
100W?还算不多。。
分表分库方案学习了。
------解决方案--------------------
(2)拦截SQL,执行简单的SQL替换,将tblxx,替换成tblxx_分区码
(3)根据分区码,选择数据库.(这一步目前未实现,我分了10表,感觉已经够多的了,50W*10,也够我用好长时间了。)

第二个感觉不太好啊,万一哪一天表名规则出现多种就麻烦了。而且要进一步实在第三种也不方便。

简单方便即在代码业务层根据分区码(或者用户名规则)动态获取数据库连接字符串和表名前缀规则,然后再抽像调用,获取数据由派生类定义,这样要增加数据库或者表名,只要派生子类即可,而且子类仅实现获取数据库和表名的方法
------解决方案--------------------
给每个用户分配一个整数ID,这样就可以准确的让某个范围内的ID映射到某一台数据库,之后再逐渐增加slave即可。 一个典型例子:QQ的号码。

一般进化到后期都是master-master-slave,双master消除单点,slave加速读取与引流线下数据。



------解决方案--------------------
探讨

给每个用户分配一个整数ID,这样就可以准确的让某个范围内的ID映射到某一台数据库,之后再逐渐增加slave即可。 一个典型例子:QQ的号码。

一般进化到后期都是master-master-slave,双master消除单点,slave加速读取与引流线下数据。

------解决方案--------------------
嗯 同意楼上的。

给每个用户分配一个整数ID,这样就可以准确的让某个范围内的ID映射到某一台数据库,之后再逐渐增加slave即可。
------解决方案--------------------
mysql分区考虑过,的确有透明的好处,但果多个库,不知如何处理?

------解决方案--------------------
订单数据分库分表,根据查询场景,个人有几下想法:
1、根据订单号单笔查询:把订单号设计好,预留出分库分表位,比如订单号总长度为64位,第61和62位代表分库分表位,用那2位mod总数据库得数据库编号,mod每库的总表数得到数据表的编号,然后查询;