关于mycat:Mycat数据库中间件

7次阅读

共计 2986 个字符,预计需要花费 8 分钟才能阅读完成。

1. 非分片字段查问

Mycat 中的路由后果是通过 分片字段 分片办法 来确定的。例如下图中的一个 Mycat 分库计划:

  • 依据 tt_waybill 表的 id 字段来进行分片
  • 分片办法为 id 值取 3 的模,依据模值确定在 DB1,DB2,DB3 中的某个分片

如果查问条件中有 id 字段的状况还好,查问将会落到某个具体的分片。例如:

mysql>select * from tt_waybill where id = 12330;

此时 Mycat 会计算路由后果

12330 % 3 = 0 –> DB1

并将该申请路由到 DB1 下来执行。
如果查问条件中没有 分片字段 条件,例如:

mysql>select * from tt_waybill where waybill_no =88661;

此时 Mycat 无奈计算路由,便发送到所有节点上执行:

DB1 –> select * from tt_waybill where waybill_no =88661;
DB2 –> select * from tt_waybill where waybill_no =88661;
DB3 –> select * from tt_waybill where waybill_no =88661;

如果该分片字段抉择度高,也是业务罕用的查问维度,个别只有一个或极少数个 DB 节点命中(返回后果集)。示例中只有 3 个 DB 节点,而理论利用中的 DB 节点数远超过这个,如果有 50 个,那么前端的一个查问,落到 MySQL 数据库上则变成 50 个查问,会极大耗费 Mycat 和 MySQL 数据库资源。

如果设计应用 Mycat 时有非分片字段查问,请思考放弃!

2. 分页排序

先看一下 Mycat 是如何解决分页操作的,如果有如下 Mycat 分库计划:
一张表有 30 份数据分布在 3 个分片 DB 上,具体数据分布如下

DB1:[0,1,2,3,4,10,11,12,13,14]
DB2:[5,6,7,8,9,16,17,18,19]
DB3:[20,21,22,23,24,25,26,27,28,29]

(这个示例的场景中没有查问条件,所以都是全分片查问,也就没有假设该表的分片字段和分片办法)

当利用执行如下分页查问时

mysql>select * from table limit 2;

Mycat 将该 SQL 申请散发到各个 DB 节点去执行,并接管各个 DB 节点的返回后果

DB1: [0,1]
DB2: [5,6]
DB3: [20,21]

但 Mycat 向利用返回的后果集取决于哪个 DB 节点最先返回后果给 Mycat。如果 Mycat 最先收到 DB1 节点的后果集,那么 Mycat 返回给利用端的后果集为 [0,1],如果 Mycat 最先收到 DB2 节点的后果集,那么返回给利用端的后果集为 [5,6]。也就是说,雷同状况下,同一个 SQL,在 Mycat 上执行时会有不同的返回后果。

在 Mycat 中执行分页操作时必须显示加上排序条件能力保障后果的正确性,上面看一下 Mycat 对排序分页的解决逻辑。
如果在后面的分页查问中加上了排序条件(如果表数据的列名为id

mysql>select * from table order by id limit 2;

Mycat 的解决逻辑如下图:

在有排序呢条件的状况下,Mycat 接管到各个 DB 节点的返回后果后,对其进行最小堆运算,计算出所有后果集中最小的两条记录 [0,1] 返回给利用。

然而,当排序分页中有 偏移量(offset)时,解决逻辑又有不同。如果利用的查问 SQL 如下:

mysql>select * from table order by id limit 5,2;

如果依照上述排序分页逻辑来解决,那么处理结果如下图:

Mycat 将各个 DB 节点返回的数据 [10,11], [16,17], [20,21] 通过最小堆计算后返回给利用的后果集是 [10,11]。可是,对于利用而言,该表的所有数据明明是 0-29 这 30 个数据的汇合,limit 5,2 操作返回的后果集应该是 [5,6],如果返回 [10,11] 则是谬误的解决逻辑。

所以 Mycat 在解决 有偏移量的排序分页 时是另外一套逻辑—— 改写 SQL。如下图:

Mycat 在下发有 limit m,n 的 SQL 语句时会对其进行改写,改写成 limit 0, m+n 来保障查问后果的逻辑正确性。所以,Mycat 发送到后端 DB 上的 SQL 语句是

mysql>select * from table order by id limit 0,7;

各个 DB 返回给 Mycat 的后果集是

DB1: [0,1,2,3,4,10,11]
DB2: [5,6,7,8,9,16,17]
DB3: [20,21,22,23,24,25,26]

通过最小堆计算后失去最小序列 [0,1,2,3,4,5,6],而后返回偏移量为 5 的两个后果为 [5,6]

尽管 Mycat 返回了正确的后果,然而认真斟酌发现这类操作的解决逻辑是及其耗费(节约)资源的。利用须要的后果集为 2 条,Mycat 中须要解决的后果数为 21 条。也就是说,对于有 t 个 DB 节点的全分片 limit m, n 操作,Mycat 须要解决的数据量为 (m+n)*t 个。比方理论利用中有 50 个 DB 节点,要执行 limit 1000,10 操作,则 Mycat 解决的数据量为 50500 条,返回后果集为10,当偏移量更大时,内存和 CPU 资源的耗费则是数十倍减少。

如果设计应用 Mycat 时有分页排序,请思考放弃!

3. 任意表 JOIN

先看一下在单库中 JOIN 中的场景。假如在某单库中有 playerteam 两张表,player 表中的 team_id 字段与 team 表中的 id 字段相关联。操作场景如下图:

JOIN 操作的 SQL 如下

mysql>select p_name,t_name from player p, team t where p.no = 3 and p.team_id = t.id;

此时能查问出后果

p_name

t_name

Wade

Heat

如果将这两个表的数据分库后,相关联的数据可能散布在不同的 DB 节点上,如下图:

这个 SQL 在各个独自的分片 DB 中都查不出后果,也就是说 Mycat 不能查问出正确的后果集。

设计应用 Mycat 时如果要进行表 JOIN 操作,要确保两个表的关联字段具备雷同的数据分布,否则请思考放弃!

4. 分布式事务

Mycat 并没有依据二阶段提交协定实现 XA 事务 ,而是只保障 prepare 阶段数据一致性的 弱 XA 事务,实现过程如下:

利用开启事务后 Mycat 标识该连贯为非主动提交,比方前端执行

mysql>begin;

Mycat 不会立刻把命令发送到 DB 节点上,等后续下发 SQL 时,Mycat 从连接池获取非主动提交的连贯去执行。

Mycat 会期待各个节点的返回后果,如果都执行胜利,Mycat 给该连贯标识为 Prepare Ready 状态,如果有一个节点执行失败,则标识为 Rollback 状态。

执行实现后 Mycat 期待前端发送 commitrollback 命令。发送 commit 命令时,Mycat 检测以后连贯是否为 Prepare Ready 状态,若是,则将 commit 命令发送到各个 DB 节点。

然而,这一阶段是无奈保障一致性的,如果一个 DB 节点在 commit 时故障,而其余 DB 节点 commit 胜利,Mycat 会始终期待故障 DB 节点返回后果。Mycat 只有收到所有 DB 节点的胜利执行后果才会向前端返回 执行胜利 的包,此时 Mycat 只能始终 waiting 直至_TIMEOUT_,导致事务一致性被毁坏。

设计应用 Mycat 时如果有分布式事务,得先看是否得保障事务得强一致性,否则请思考放弃!

正文完
 0