如果数据库表没有主键需要分片,数据库主键应该怎么设计

当前位置: >>
MyCAT In Action 中文版MyCAT 1.2 版本MyCAT 介绍什么是 MyCAT?简单的说,MyCAT 就是: ? ? ? ? ? ? 一个彻底开源的,面向企业应用开发的“大数据库集群” 支持事务、ACID、可以替代 Mysql 的加强版数据库 一个可以视为“Mysql”集群的企业级数据库,用来替代昂贵的 Oracle 集群 一个融合内存缓存技术、Nosql 技术、HDFS 大数据的新型 SQL Server 结合传统数据库和新型分布式数据仓库的新一代企业级数据库产品 一个新颖的数据库中间件产品MyCAT 的目标是:低成本的将现有的单机数据库和应用平滑迁移到“云”端,解决数据存 储和业务规模迅速增长情况下的数据瓶颈问题。 MyCAT 的关键特性: ? ? ? 支持 SQL 92 标准 支持 Mysql 集群,可以作为 Proxy 使用 支持 JDBC 连接 ORACLE、DB2、SQL Server,将其模拟为 MySQL Server 使用 支持 galera for mysql 集群,percona-cluster 或者 mariadb cluster,提供高可用性?数据分片集群? ? ? ? ? 自动故障切换,高可用性 支持读写分离,支持 Mysql 双主多从,以及一主多从的模式 支持全局表,数据自动分片到多个节点,用于高效表关联查询 支持独有的基于 E-R 关系的分片策略,实现了高效的表关联查询 多平台支持,部署和实施简单MyCAT 的优势: ??? ?基于阿里开源的 Cobar 产品而研发,Cobar 的稳定性、可靠性、优秀的架构和性 能,以及众多成熟的使用案例使得 MyCAT 一开始就拥有一个很好的起点,站在巨 人的肩膀上,我们能看到更远。 广泛吸取业界优秀的开源项目和创新思路,将其融入到 MyCAT 的基因中,使得 MyCAT 在很多方面都领先于目前其他一些同类的开源项目,甚至超越某些商业产 品。 MyCAT 背后有一只强大的技术团队,其参与者都是 5 年以上资深软件工程师、架 构师、DBA 等,优秀的技术团队保证了 MyCAT 的产品质量。 MyCAT 并不依托于任何一个商业公司,因此不像某些开源项目,将一些重要的特 性封闭在其商业产品中,使得开源项目成了一个摆设。MyCAT 的长期路线规划: ? 在支持 Mysql 的基础上,后端增加更多的开源数据库和商业数据库的支持,包括原 生支持 PosteSQL、FireBird 等开源数据库,以及通过 JDBC 等方式间接支持其他非 开源的数据库如 Oracle、DB2、SQL Server 等 实现更为智能的自我调节特性,如自动统计分析 SQL,自动创建和调整索引,根据 数据表的读写频率,自动优化缓存和备份策略等 实现更全面的监控管理功能 与 HDFS 集成,提供 SQL 命令,将数据库装入 HDFS 中并能够快速分析 集成优秀的开源报表工具,使之具备一定的数据分析的能力? ? ? ?MyCAT 架构Client (MySQL CLI/JDBC/ODBC/…) FrontMySQL Socket Protocol HandlerSQL ParserSQL Router Server SQL ExecutorDataNodeHeartBeat CheckerMySQL instance AMySQL instance C StorageMySQL instance BMore…. 如图所示:MyCAT 使用 Mysql 的通讯协议模拟成了一个 Mysql 服务器,并建立了 完整的 Schema(数据库)、Table (数据表)、User(用户)的逻辑模型,并将这套逻辑模 型映射到后端的存储节点 DataNode(MySQL Instance)上的真实物理库中,这样一来,所 有能使用 Mysql 的客户端以及编程语言都能将 MyCAT 当成是 Mysql Server 来使用,不必开 发新的客户端协议。 当 MyCAT 收到一个客户端发送的 SQL 请求时,会先对 SQL 进行语法分析和检查, 分析的结果用于 SQL 路由,SQL 路由策略支持传统的基于表格的分片字段方式进行分片, 也支持独有的基于数据库 E-R 关系的分片策略,对于路由到多个数据节点(DataNode)的 SQL,则会对收到的数据集进行“归并”然后输出到客户端。 SQL 执行的过程,简单的说,就是把 SQL 通过网络协议发送给后端的真正的数据库 上进行执行,对于 Mysql Server 来说,是通过 Mysql 网络协议发送报文,并解析返回的结 果,若 SQL 不涉及到多个分片节点,则直接返回结果,写入客户端的 SOCKET 流中,这个 过程是非阻塞模式(NIO)。 DataNode 是 MyCAT 的逻辑数据节点,映射到后端的某一个物理数据库的一个 Database,为了做到系统高可用,每个 DataNode 可以配置多个引用地址(DataSource), 当主 DataSource 被检测为不可用时,系统会自动切换到下一个可用的 DataSource 上,这 里的 DataSource 即可认为是 Mysql 的主从服务器的地址。MyCAT 逻辑库与任何一个传统的关系型数据库一样,MyCAT 也提供了“数据库”的定义,并有 用户授权的功能,下面是 MyCAT 逻辑库相关的一些概念: ? schema:逻辑库,与 MySQL 中的 Database(数据库)对应,一个逻辑库中定义了所 包括的 Table。 ? table:表,即物理数据库中存储的某一张表,与传统数据库不同,这里的表格需 要声明其所存储的逻辑数据节点 DataNode,这是通过表格的分片规则定义来实现 的,table 可以定义其所属的“子表(childTable)”,子表的分片依赖于与“父表” 的具体分片地址,简单的说,就是属于父表里某一条记录 A 的子表的所有记录都 与 A 存储在同一个分片上。 ? 分片规则:是一个字段与函数的捆绑定义,根据这个字段的取值来返回所在存储 的分片(DataNode)的序号,每个表格可以定义一个分片规则,分片规则可以灵 活扩展,默认提供了基于数字的分片规则,字符串的分片规则等。 ? DataNode: MyCAT 的逻辑数据节点,是存放 table 的具体物理节点,也称之为分片 节点,通过 DataSource 来关联到后端某个具体数据库上,一般来说,为了高可用 性,每个 DataNode 都设置两个 DataSource,一主一丛,当主节点宕机,系统自动 切换到从节点。 DataSource:定义某个物理库的访问地址,用于捆绑到 Datanode 上。?MyCAT 目前通过配置文件的方式来定义逻辑库和相关配置: ? ? ? MYCAT_HOME/conf/schema.xml 中定义逻辑库,表、分片节点等内容 MYCAT_HOME/conf/rule.xml 中定义分片规则 MYCAT_HOME/conf/server.xml 中定义用户以及系统相关变量,如端口等。下图给出了 MyCATd 一个可能的逻辑库到物理库(Mysql 的完整映射关系),可以看出其 强大的分片能力以及灵活的 Mysql 集群整合能力。schemaTable ATable BDatanode 1Datanode 2Datanode 3Datanode 4Database aDatabase c Database e Database b 192.168.0.1 192.168.0.2 192.168.0.3分片策略MyCAT 支持水平分片与垂直分片: ? ? 水平分片:一个表格的数据分割到多个节点上,按照行分隔。 垂直分片:一个数据库中多个表格 A,B,C,A 存储到节点 1 上,B 存储到节点 2 上,C 存储到节点 3 上。MyCAT 通过定义表的分片规则来实现分片,每个表格可以捆绑一个分片规则,每个分 片规则指定一个分片字段并绑定一个函数,来实现动态分片算法。以常用的基于整数映射 的分片函数 org.MyCAT.route.function.PartitionByFileMap 为例,此函数通过一个配置文件来 确定映射关系,以下面的 sharding-by-intfile 这个分片规则为例:&tableRule name=&sharding-by-intfile&& &rule& &columns&sharding_id&/columns& &algorithm&hash-int&/algorithm& &/rule& &/tableRule& &tableRule name=&auto-sharding-long&& &rule& &columns&id&/columns& &algorithm&rang-long&/algorithm& &/rule& &/tableRule& &function name=&hash-int& class=&org.MyCAT.route.function.PartitionByFileMap&& &property name=&mapFile&&partition-hash-int.txt&/property& &/function& &function name=&rang-long& class=&org.MyCAT.route.function.AutoPartitionByLong&& &property name=&mapFile&&autopartition-long.txt&/property& &/function&partition-hash-int.txt 的文件如下: 10=1 表明当字段 sharding_id 取值为 10000 的时候,返回分片节点 ID 为 0,以此类推。 Schema.xml 中定义 customer 表的分片规则为此规则: &table name=&customer& dataNode=&dn1,dn2& rule=&sharding-by-intfile& /& 于是 customer 按照字段 sharding_id 进行水平分片,分片存储在两个数据节点 dn1,dn2 上。 如何知道某个 SQL 在哪个分片上执行? 用 explain sql 语句: explain select * from customer where sharding_id=10000根据业务场景和数据特点,可以选用以下的分片规则: ? auto-sharding-long 主键自动增长的数字,按照范围进行自动分片,比如 0-200 万 的数据在分片节点 0,200-400 万的数据在分片节点 2,依次类推,根据数据库服务 器的性能,可以每个分片存储 100-500 条记录之间,此种方式,每个分片表一个独 立的自增长 ID 机制,确保记录的连续性。conf/ autopartition-long.txt 中定义了分段 范围与分片 ID 的关系。 ?sharding-by-intfile,表中有字段 sharding_id,其类型为整数,对应具体的业务含 义,比如 10000 对应电信,10010 对应联通,此外,按照省份编码进行定义,也是 可行的方式,为了效率,编码被映射为数字而不是字符串,conf/ partition-hashint.txt, 定义了某个整数值到某个分片 id 的映射关系。 mod-long,对某些表,我们基本上很少会涉及到范围查询的,只根据某个字段(最 常见是主键)进行查找定位,则可以用求余的方式,随机分配到其中一个节点上。?所有的分片规则都在 rule.xml 中定义,不同的表根据需求,定义不同的分片规则。对于某些不分片的表格,或者分片规则一样的表格,table 的定义可以用简化的方式来写, 如:&table name=&customer,product& rule=&auto-sharding-long& /& 。对于此种方式,name 中定义的这些表格具有相同的属性,并且都不能有 childTable 元素。基于 E-R 关系分片策略传统的数据库分片方式都是基于单个表格,对于表关联这种操作,则很难处理,考 虑下面的分片模型,customer 与 orders 分片在不同节点上,orders 的 parent_id 字段存放父 表 customer 的主键:customer Dn1(customer) Id:1 Id:2 Dn2(customer) Id:3 Id:4 Dn3(customer) Id:5 Id:6orders Dn1(orders) Parent_id:1 Parent_id:3Dn2(orders) Parent_Id:2 Parent_id :5 Dn3(orders) Parent_id :1 Parent_id:3 为了能够执行 customer 与 orders 的联合查询,意味着分片表的数据必须要跨节点进行 网络传输,以上图为例: ? ? ? DN1 节点上的 orders 表 JOIN 时候需要 DN1 和 DN2 的节点 DN2 节点上的 orders 表 JOIN 时候需要 DN1 和 DN3 的节点 DN3 节点上的 orders 表 JOIN 时候需要 DN1、DN2、DN3 的节点目前这种方式的 JOIN,业界没有很好的解决办法,而且实现起来都很复杂,性能也达 不到企业应用开发的要求。 MyCAT 借鉴了 NewSQL 领域的新秀 Foundation DB 的设计思路,Foundation DB 创新性 的提出了 Table Group 的概念,其将子表的存储位置依赖于主表,并且物理上紧邻存放, 因此彻底解决了 JION 的效率和性能问题,根据这一思路,提出了基于 E-R 关系的数据分片 策略,子表的记录与所关联的父表记录存放在同一个数据分片上。 以上述例子为例,schema.xml 中定义如下的分片配置: &table name=&customer& dataNode=&dn1,dn2& rule=&sharding-by-intfile&& &childTable name=&orders& joinKey=&customer_id& parentKey=&id&/& &/table& customer 采用 sharding-by-intfile 这个分片策略,分片在 dn1,dn2 上,orders 依赖父表 进行分片,两个表的关联关系为 orders.customer_id=customer.id。于是数据分片和存储的 示意图如下: customer Dn1(customer) Id:1 Id:2 Dn2(customer) Id:3 Id:4 orders Dn1(orders) Parent_id:1 Parent_id:2Dn2(orders) Parent_Id:3 Parent_id :4 这样一来,分片 Dn1 上的的 customer 与 Dn1 上的 orders 就可以进行局部的 JOIN 联合,Dn2 上也如此,再合并两个节点的数据即可完成整体的 JOIN,试想一下,每个分片 上 orders 表有 100 万条,则 10 个分片就有 1 个亿,基于 E-R 映射的数据分片模式,基本 上解决了 80%以上的企业应用所面临的问题。 多对多的表格如何处理?多对多的表格通常情况下,有以下几种: ? ? 主表+关系表+字典表 主表 A+关系表+主表 B对于第一种,字典表可以被定义为“全局表”,字典表的记录规模可以在几千到几 十万之间,基本是变动比较少的表,由 MyCAT 自动实时同步到所有分片,这样就可以三 个表都做 JOIN 操作了。 对于第二种,需要从业务角度来看,关系表更偏向哪个表,即“A 的关系”还是 “B 的关系”,来决定关系表跟从那个方向存储。目前还暂时无法很好支持这种模式下的 的 3 个表之间的关联。未来版本中将考虑将中间表进行双向复制,以实现从 A-关系表 以 及 B-关系表的双向关联查询。 关于全局表的实现方式,全局表在数据插入或更新的时候,会自动在全局表定义的 所有数据节点上执行相同的操作,以保证所有数据节点都一致,由于这个特性,全局表可 以跟任何分片或不分片的表格进行 JOIN 操作。对数据更新不频繁的,规模不是很大的 (100 万之内)的表都可以定义为 MyCAT 的全局表,以实现用存储换性能的目标。主键分片 VS 非主键分片主键分片还是非主键分片,这个问题并不是很难,当你没人任何字段可以作为分片 字段的时候,主键分片就是唯一选择,其优点是按照主键的查询最快,当采用自动增长的 序列号作为主键时,还能比较均匀的将数据分片在不同的节点上。 若有某个合适的业务字段比较合适作为分片字段,则建议采用此业务字段分片,选 择分片字段的条件如下: ? ? 尽可能的比较均匀分布数据到各个节点上 该业务字段是最频繁的或者最重要的查询条件常见的除了主键之外的其他可能分片字段有“订单创建时间”、店铺类别或所在省 等。当你找到某个合适的业务字段作为分片字段以后,不必纠结于“牺牲了按主键查询记 录的性能”,因为在这种情况下,MyCAT 提供了“主键到分片”的内存缓存机制,热点数 据按照主键查询,丝毫不损失性能。做法如下:对于非主键分片的 TABLE,填写属性 primaryKey,此时 MyCAT 会将你根据主键查询的 SQL 语句的第一次执行结果进行分析,确定该 Table 的某个主键在什么分片上,并进行主 键到分片 ID 的缓存,以下面 SQL 为例,由于 id 不是 orders 的分片字段,因此这个 SQL 第 一次会发送给所有分片去执行: select * from orders where id=1;执行完成以后:在缓存 TableID2DataNodeCache.TESTDB_ORDERS 中放入一条信息,key 为主键的值, value 为分片 ID,当我们再次执行上述语句,MyCAT 就直接将 SQL 发往 dn2 了:对于多个主键的查询,一样可以自动优化:如 Select * from orders where id in (1,2,3) , 则会分别存储 1、2、3 这三个主键到分片的缓存关系。 设想下,每个表有 5000 万数据,10%的热点数据经常按照主键查询,5000 万 *10%=500 万,缓存上述信息大概需要 1.5G 内存,通过分析缓存使用信息,就可以最精确 的调优这笔缓存的内存。通过连接 MyCAT 的 9066 管理端口,执行 show @@cache,可以 显示当前缓存的使用情况: 更多内容,参照 MyCAT 性能调优手册。SQL 99 规范MYCAT 支持 SQL 99 规范,包括 DDL 语句的支持,部分 MYSQL 特定的语法并不支 持,但 MYCAT 1.2 通过了一个特殊方式来解决特殊 SQL 的问题,即通过 MYSQL 注解方 式,以下面的 SQL 语句为例: /*!mycat select id from travelrecord where id=2*/ select * from travelrecord where id=2; 其中/*! Xxxx */为 MYSQL 特殊注解语法的格式,注解内以 mycat 开头,说明是 mycat 处理的注解,这里放置一个符合 SQL 99 的 SQL 语句,用来告诉 MYCAT,用此语句 进行语法解析和路由分析,然后将注释后面的真正的 SQL select * from travelrecord where id=2 提交到匹配的路由上执行,并返回结果。 比如 MyCAT 并不支持 mysql 的 select into 语法,若 select into 语法涉及到的表是不 分片的,则可以如下来写注释,让此 SQL 能执行通过: /*!mycat insert into B*/ select * from A insert into B备注:后续版本注解格式修改为 /*!mycat: sql = select id from travelrecord where id=2*/ select * from travelrecord where id=2;MyCAT 全局表一个真实的业务系统中,往往存在大量的类似字典表的表格,它们与业务表之间可 能有关系,这种关系,可以理解为“标签”,而不应理解为通常的“主从关系”,这些表 基本上很少变动,可以根据主键 ID 进行缓存,下面这张图说明了一个典型的“标签关 系”图:省份表厂商表网络设备设备状态表设备类型表 在分片的情况下,当业务表因为规模而进行分片以后,业务表与这些附属的字典表 之间的关联,就成了比较棘手的问题,考虑到字典表具有以下几个特性: ? ? ? 变动不频繁 数据量总体变化不大 数据规模不大,很少有超过数十万条记录。鉴于此,MyCAT 定义了一种特殊的表,称之为“全局表”,全局表具有以下特性: ? ? ? 全局表的插入、更新操作会实时在所有节点上执行,保持各个分片的数据一致性 全局表的查询操作,只从一个节点获取 全局表可以跟任何一个表进行 JOIN 操作将字典表或者符合字典表特性的一些表定义为全局表,则从另外一个方面,很好的解 决了数据 JOIN 的难题。通过全局表+基于 E-R 关系的分片策略,MyCAT 可以满足 80%以上 的企业应用开发。 全局表配置比较简单,不用写 Rule 规则,如下配置即可: &table name=&company& primaryKey=&ID& type=&global& dataNode=&dn1,dn2,dn3& /& 需要注意的是,全局表每个分片节点上都要有运行创建表的 DDL 语句。高可用性以及读写分离MyCAT 的读写分离机制如下: ? ? ? 事务内的 SQL,全部走写节点,除非某个 select 语句以注释/*balance*/开头 自动提交的 select 语句会走读节点,并在所有可用读节点中间随机负载均衡 当某个主节点宕机,则其全部读节点都不再被使用,因为此时,同步失败,数据 已经不是最新的,MYCAT 会采用另外一个主节点所对应的全部读节点来实现 select 负载均衡。 ? 当所有主节点都失败,则为了系统高可用性,自动提交的所有 select 语句仍将提交 到全部存活的读节点上执行,此时系统的很多页面还是能出来数据,只是用户修改 或提交会失败。MyCAT 的读写分离的配置如下: dataHost 的 balance 属性设置为: ? ? 0,不开启读写分离机制 1,全部的 readHost 与 stand by writeHost 参与 select 语句的负载均衡,简单的说, 当双主双从模式(M1-&S1,M2-&S2,并且 M1 与 M2 互为主备),正常情况下, M2,S1,S2 都参与 select 语句的负载均衡。 2,所有的 readHost 与 writeHost 都参与 select 语句的负载均衡,也就是说,当系 统的写操作压力不大的情况下,所有主机都可以承担负载均衡。 一个 dataHost 元素,表明进行了数据同步的一组数据库,DBA 需要保证这一组数 据库服务器是进行了数据同步复制的。writeHost 相当于 Master DB Server,而旗下 的 readHost 则是与从数据库同步的 Slave DB Server。当 dataHost 配置了多个 writeHost 的时候,任何一个 writeHost 宕机,Mycat 都会自动检测出来,并尝试切 换到下一个可用的 writeHost。 MyCAT 支持高可用性的企业级特性,根据您的应用特性,可以配置如下几种策略: ? ? ? 后端数据库配置为一主多从,并开启读写分离机制。 后端数据库配置为双主双从(多从),并开启读写分离机制 后端数据库配置为多主多从,并开启读写分离机制?后面两种配置,具有更高的系统可用性,当其中一个写节点(主节点)失败后,Mycat 会 侦测出来(心跳机制)并自动切换到下一个写节点,MyCAT 在任何时候,只会往一个写 节点写数据。 下面是典型的双主双从的 Mysql 集群配置: MyCAT) M1(writeHost)M2(writeHost)) S1(readHost)) S2(readHost)) ) Log4j.xml 中配置日志输出级别为 debug 时,当选择节点的时候,会输出如下日志:16:37:21.660 DEBUG [Processor0-E3] (PhysicalDBPool.java:333) -select read source hostM1 for dataHost:localhost1 16:37:21.662 DEBUG [Processor0-E3] (PhysicalDBPool.java:333) -select read source hostM1 for dataHost:localhost1 根据这个信息,可以确定某个 SQL 发往了哪个读(写)节点,据此可以分析判断是否发生了读 写分离。全局序列号全局序列号是 MyCAT 提供的一个新功能,为了实现分库分表情况下,表的主键是 全局唯一,而默认的 MySQL 的自增长主键无法满足这个要求。全局序列号的语法符合标 准 SQL 规范,其格式为: next value for MYCATSEQ_GLOBAL 其中 MYCATSEQ_GLOBAL 是序列号的名字,MyCAT 自动创建新的序列号,免去了开 发的复杂度,另外,MyCAT 也提供了一个全局的序列号,名称为:MYCATSEQ_GLOBAL。 注意,MYCATSEQ_必须大写才能正确识别。 MyCAT 温馨提示:实践中,建议每个表用自己的序列号,序列号的命名建议为 MYCATSEQ _tableName_ID_SEQ。SQL 中使用说明 自定义序列号的标识为:MYCATSEQ_XXX ,其中 XXX 为具体定义的 sequence 的名 称,应用举例如下: 使用默认的全局 sequence : insert into tb1(id,name) values(next value for MYCATSEQ_GLOBAL,'micmiu.com'); 使用自定义的 sequence : insert into tb2(id,name) values(next value for MYCATSEQ_MY1,'micmiu.com'); 获取最新的值 Select next value for MYCATSEQ_xxxMyCAT 目前已经提供了一个本地配置版的实现,下面是配置说明: 配置说明 配置文件:sequence_conf.properties 格式说明: XXX.HISIDS= 1-100,501-800, //使用过得历史分段 XXX.MINID=10001 //当前可用分段的最小值 XXX.MAXID=20000 //当前可用分段的最大值 XXX.CURID=10000 //当前可用分段的当前值全局 sequence 配置如下: GLOBAL.HISIDS= GLOBAL.MINID=1 GLOBAL.MAXID=50000 GLOBAL.CURID=10000 自定义 sequence 配置如下: MY1.HISIDS= MY1.MINID=101 MY1.MAXID=200 MY1.CURID=152Mysql 数据库表格保存全局序列号的配置如下: Serfver.xml 中启用,&property name=&sequnceHandlerType&&1&/property& ? 在某个分区(dataNode)数据库上创建序列号相关的表格和函数,SQL 脚本在 doc 目录下的 sequnce-sql.txt 中,需要在数据库上而非 Mycat 上执行。 ? Mycat_home/conf/quence_db_conf.properties 中记录了 sequnce 所存放的 db 对应的配置 信息。 #sequence stored in datanode GLOBAL=dn1 COMPANY=dn1 CUSTOMER=dn1 ? 在 sequnce 表中,插入相应的 sequnce 记录,并确定其初始值,以及增长步长,步长建议一个 合适的范围,比如 50-500,需要在数据库上而非 Mycat 上执行。 INSERT INTO MYCAT_SEQUENCE VALUES ('GLOBAL', 0, 100); ? 修改 sequnce 的当前值为某个新值,需要在数据库上而非 Mycat 上执行。 SELECT mycat_seq_curval('GLOBAL'); 提示:步长选择多大,取决与你数据插入的 TPS,假如是每秒 1000 个,则步长为
万,也不是很大,即 10 秒会重新从数据库读取下一批次的序列号值。JDBC 方式支持其他数据库从 MyCAT 1.2 开始,实现了 JDBC 通用方式连接后端其他数据库,如 Oracle、SQL Server、DB2 等,在客户端,仍然可以把 MyCAT 视作是一个 MySQL 服务器。 配置方式如下,首先将符合 JDBC 4 标准的驱动 JAR 包放到 MYCAT\lib 下,注意检 查驱动 JAR 包中包括如下目录结构的文件: META-INF\services\java.sql.Driver文件内容为驱动的类名: schema.xml 中如下定义 JDBC 的 DateHost:&dataHost name=&jdbchost& maxCon=&1000& minCon=&10& balance=&0& dbType=&mysql& dbDriver=&jdbc&& &heartbeat&select user()&/heartbeat& &writeHost host=&hostM1& url=&jdbc:mysql://localhost:3306& user=&root& password=&123456&& &/writeHost& &/dataHost&MyCAT 配置Server.xml 里面定义系统参数、用户权限,Mycat 目前支持只读与读写两种权限,readOlny 表示只读权限。&user name=&test&& &property name=&password&&test&/property& &property name=&schemas&&TESTDB&/property& &property name=&readOnly&&true&/property& &/user&SQL 拦截SQL 拦截是一个比较有用的高级技巧,用户可以写一个 java 类,将传入 MyCAT 的 SQL 进 行改写然后交给 Mycat 去执行,此技巧可以完成如下一些特殊功能: ? ? ? 捕获和记录某些特殊的 SQL 处于性能优化的考虑,改写 SQL,比如改变查询条件的顺序或增加分页限制 将某些 Select SQL 强制设置为 Read 模式,走读写分离(很多事务框架很难剥离事 务中的 Select SQL ? 其他。。。。 用法是在 Server.xml 中配置系统参数,指定自己的 SQL 拦截器的 Java 实现类:&system& &property name=& sqlInterceptor&&org.opencloudb.interceptor.impl.DefaultSqlInterceptor&/propert y& &/system& 默认的拦截器实现了 Mysql 转义字符的过滤转换,SQL 拦截器的实现很简单: /** * escape mysql escape letter */ @Override public String interceptSQL(String sql, int sqlType) { if (sqlType == ServerParse.UPDATE || sqlType == ServerParse.INSERT||sqlType == ServerParse.SELECT||sqlType == ServerParse.DELETE) { return sql.replace(&\\'&, &''&); } else { } }MyCAT 高可用性方案HAProxy 或者 MyCAT Cluster 做负载均衡,后端一组 MyCAT Server,MyCAT Server 之后的 MySQL 数据库可以有以下两种选择: ? MYSQL 主从复制,当主节点失败,自动切换到从节点写数据。 galera for mysql 集群,percona-cluster 或者 mariadb cluster? MyCAT 与 percona-cluster 配合,schema.xml 配置如下:&dataHost name=&localhost1& maxCon=&1000& minCon=&10& balance=&0& writeType=&1& dbType=&mysql& dbDriver=&native&& &heartbeat&select user()&/heartbeat& &writeHost host=&hostM1& url=&localhost:3306& user=&root& password=&123456&/& &writeHost host=&hostM2& url=&localhost:3317& user=&root& password=&123456&/& &writeHost host=&hostM3& url=&localhost:3319& user=&root& password=&123456&/& &/dataHost& 有几个 percona-cluster 节点,writeHost 就写几个,同时 writeType 必须设为 1,这种模 式下,没有 readHost. 当任何一个 writeHost 失败,会自动排除,恢复以后,自动加入写节点。快速上手是用 Java 开发,需要有 JAVA 运行环境,若本机没有,则需要下载安装: http://www.java.com/zh_CN/ 获取 MyCAT 的最新开源版本,项目主页 http://code.google.com/p/MyCAT/ 目前最新代码暂时在淘宝上托管,二进制包下载地址: http://code.taobao.org/svn/openclouddb/downloads/ windows 下可以下载 Mycat-server-xxxx.ZIP,linux 下可以下载 tar.gz 解开在某个目录下,注 意,目录不能有空格,在 Linux(Unix)下,建议放在/usr/local/MyCAT 目录下,如下面类似 的:下面是修改 MyCat 用户的密码方式(仅供参考)目录解释如下: Bin 程序目录,存放了 window 版本和 linux 版本,除了提供封装成服务的版本之外,也提 供了 nowrap 的 shell 脚本命令,方便大家选择和修改,进入到 bin 目录: ? Windows 下 运行: mycat.bat console 在控制台启动程序,也可以装载成服务,若此 程序运行有问题,也可以运行 startup_nowrap.bat,确保 java 命令可以在命令执 行。 ? Linux 下运行:mycat console,首先要 chmod +x mycatWarp 方式的命令,可以安装成服务并启动或停止。 ? ?mycat install (可选) mycat start注意,wrap 方式的程序,其 JVM 配置参数在 conf/wrap.conf 中,可以修改为合适的参 数,参数调整参照 http://wrapper.tanukisoftware.com/doc/english/properties.html。用下 面是一段实例: # Java Additional Parameters wrapper.java.additional.5=-XX:MaxDirectMemorySize=2G wrapper.java.additional.6=-Dcom.sun.management.jmxremote # Initial Java Heap Size (in MB) wrapper.java.initmemory=2048 # Maximum Java Heap Size (in MB) wrapper.java.maxmemory=2048 若启动报内存不够,可以试着将上述内存都改小,改为 1G 或 500M。 Conf 目录下存放配置文件,server.xml 是 Mycat 服务器参数调整和用户授权的配置 文件,schema.xml 是逻辑库定义和表以及分片定义的配置文件,rule.xml 是分片规则的配 置文件,分片规则的具体一些参数信息单独存放为文件,也在这个目录下,配置文件修 改,需要重启 Mycat 或者通过 9066 端口 reload。 日志存放在 logs/mycat.log 中,每天一个文件,日志的配置是在 conf/log4j.xml 中,根据自 己的需要,可以调整输出级别为 debug,debug 级别下,会输出更多的信息,方便排查问 题。 建议本地有一个 Mysql Server,若没有,建议安装一个,下载地址: http://dev.mysql.com/downloads/mysql/5.5.html#downloads 启动 Mysql,确保能正常登录访问数据,msyql 命令行工具 mysql\bin\mysql.exe 建议加入 PATH 路径中,为了方便使用。 用命令行工具或图形化客户端,连接 MYSQL,创建 DEMO 所用三个分片数据库; CREATE database db1; CREATE database db2; CREATE database db3; 注意:若是 LINUX 版本的 MYSQL,则需要设置为 Mysql 大小写不敏感,否则可能会发生表 找不到的问题。在 MySQL 的配置文件中 my.ini [mysqld] 中增加一行 lower_case_table_names = 1编辑 MYCAT_HOME/conf/schema.xml 文件,修改 dataHost 对应的连接信息:注意 writeHost/readHost 中的 location,user,password 的值符合你所采用的 Mysql 的连接信 息。修改完成后保存,进入到 MYCAT_HOME/bin 目录下,执行启动命令:startup.bat ,启动成 功以后显示如下信息:注意,默认数据端口为 8066,管理端口为 9066。客户端也可以用图形化的客户端如:mysqlworkbench、 navicat 、以及一些 基于 Java 的数据库客户端来访问,注意要填写端口号 8066,以及 database 为 TESTDB。命令行运行:mysql -utest -ptest -h127.0.0.1 -P8066 -DTESTDB 就能访问 OpenCloudDB 了, 以下操作都在此命令行里执行(JDBC 则将 mysql 的 URL 中的端口 3306 改为 8066 即可) 提示:访问 MyCAT 的用户账号和授权信息是在 conf/server.xml 文件中配置,而 MyCAT 用 来连接后端 MySQL 库的用户名密码信息则在 conf/schema.xml 中,这是两套完全独立的系 统,类似的还有 MyCAT 的逻辑库(schema),逻辑表(table)也是类似的。 Employee 表,是根据规则 sharding-by-intfile (分片字段为 sharding_id)进行分片。创建 employee 表:输入如下 SQL create table employee (id int not null primary key,name varchar(100),sharding_id int not null); 运行 explain 指令,查看该 SQL 被发往哪些分片节点执行: explain create table employee (id int not null primary key,name varchar(100),sharding_id int not null);建议参照 schema.xml 中 employee 表的定义,以及其分片规则,来看看什么数据会出现在 dn1 上,什么数据会出现在 dn2 上。 温馨提示:explain 可以用于任何正确的 SQL 上,其作用是告诉你,这条 SQL 会路由到哪 些分片节点上执行,这对于诊断分片相关的问题很有帮助。另外,explain 可以安全的执 行多次,它仅仅是告诉你 SQL 的路由分片,而不会执行该 SQL。 插入数据: insert into employee(id,name,sharding_id) values(1,'leader us',10000); insert into employee(id,name,sharding_id) values(2, 'me',10010); insert into employee(id,name,sharding_id) values(3, 'mycat',10000); insert into employee(id,name,sharding_id) values(4, 'mydog',10010);company 表是根据规则 auto-sharding-long(主键范围)进行分片。创建 company 表:输入 如下 SQL create table company(id int not null primary key,name varchar(100)); 录入数据: insert into company(id,name) values(1,'hp'); insert into company(id,name) values(2,'ibm'); insert into company(id,name) values(3,'oracle'); 你会看到三个分片上都插入了 3 条数据,因为 company 定义为全局表,用 explain 来确认 这个情况: explain insert into company(id,name) values(1,'hp') 返回 3 个节点的信息: | DATA_NODE | SQL |+-----------+---------------------------------------------+ | dn1 | dn2 | dn3 | insert into company(id,name) values(1,'hp') | | insert into company(id,name) values(1,'hp') | | insert into company(id,name) values(1,'hp') |+-----------+---------------------------------------------+ 创建客户表: create customer: create table customer(id int not null primary key,name varchar(100),company_id int not null,sharding_id int not null); 插入数据: insert into customer (id,name,company_id,sharding_id )values(1,'wang',1,10000); //stored in db1; insert into customer (id,name,company_id,sharding_id )values(2,'xue',2,10010); //stored in db2; insert into customer (id,name,company_id,sharding_id )values(3,'feng',3,10000); //stored in db1; 查询结果: Select * explain Select * (确认数据是分片存储) 创建表格 orders,并插入数据: create table orders (id int not null primary key ,customer_id int not null,sataus int ,note varchar(100) ); insert into orders(id,customer_id) values(1,1); //stored in db1 because customer table with id=1 stored in db1 insert into orders(id,customer_id) values(2,2); //stored in db2 because customer table with id=1 stored in db2 explain insert into orders(id,customer_id) values(2,2); select customer.name ,orders.* from customer ,orders where customer.id=orders.customer_travelrecord 根据 ID 主键的范围进行分片: create travelrecord: create table travelrecord (id bigint not null primary key,user_id varchar(100),traveldate DATE, fee decimal,days int); insert into travelrecord (id,user_id,traveldate,fee,days) values(1,'wang','',510.5,3);explain insert into travelrecord (id,user_id,traveldate,fee,days) values(2000001,'wang','',510.5,3); 这个 ID 就存放在分片 2 上了看到支持跨分片的 JOIN!热点新闻,用取摸的方式随机分配到 dn1,dn2,dn3 上 create table hotnews(id int not null primary key ,title varchar(400) ,created_time datetime); 插入数据 insert into hotnews(id,title,created_time) values(1,'first',now()); 在分片 1 上 而 Id 为 5,则到 dn3 上,5%3=2 ,即对应 dn3 的 index其他: goods 表 create table goods(id int not null primary key,name varchar(200),good_type tinyint,good_img_url varchar(200),good_created date,good_desc varchar(500), price double); 一起探索 MyCAT 的奇妙新世界吧! QQ 群:管理监控:MyCAT 自身有类似其他数据库的管理监控方式,通过 Mysql 命令行,登录管理端口 (9066)执行相应的 SQL,进行管理 mysql -utest -ptest -P9066 show @@ 此命令会显示所有的管理监控命令,另外请参照《Mycat 命令行监控指 南.docx》这个文档来深入了解。欢迎有志于大数据、分布式计算、数据库算法和优化等方面的大侠加入。附: MyCAT 1.0GA 版与 Cobar 1.2.7 最新版的对比 特性 Cobar MyCAT 支持 Mysql 集群 跨 Msyql 分表 NIO 前端 NIO 后端 全局表 基于 E-R 关系的分片策略 跨节点数据的归并、排序、分页 后端连接池共享(一台 MSQL 上的 所有物理连接贡献) 数据库读写分离和负载均衡 独立的均衡组件 完善的 WEB 管理系统 数据库智能优化 社区及活跃度Y Y Y N N N N NY Y Y Y Y Y Y YN N N N 目前已经停止维护Y Y Y Y(正在研发) 众多互联网公司的资 深架构师和工程师参 与研发、测评以及 BUG 修复另外,MyCAT 修复了众多 Cobar 的 BUG 还做了很多优化,以下是比较重要的一部分: ? Mysql 连接数过大,拒绝连接后,Cobar 报错,indexoutof bound,导致难以排查故障 原因 当前活跃连接数和空闲连接数的计算存在 BUG 当某些 SQL 执行比较慢,会导致 Cobar 卡死,可以用 select sleep(300) from anytalbe,此 SQL 执行不到一百个,就导致 Cobar 假死,无法响应新的请求 在某些情况下,后端连接得不到释放,另外,Cobar 没有控制后端总数,当高并发 的情况下,会创建更多连接,导致数据库压力增大,系统可靠性降低。? ??
更多搜索:
All rights reserved Powered by
文档资料库内容来自网络,如有侵犯请联系客服。}

我要回帖

更多关于 数据库建表主键 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信