加入收藏 | 设为首页 | 会员中心 | 我要投稿 财气旺网 - 财气网 (https://www.caiqiwang.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

Mycat的运用 - 03.全局序列号

发布时间:2022-02-25 15:23:55 所属栏目:MySql教程 来源:互联网
导读:02配置篇说到tb1表按照主键id进行了分片, 实际工作中还会经常按业务字段分片, 这次有tb3表, 按user_id分片, 依上文思路, 先调整下涉及到的配置文件. 1. 在schema.xml中, 添加tb3表的配置. table name=tb3 dataNode=dnTest1,dnTest2 rule=mod-long-user_id/ 2
      02配置篇说到tb1表按照主键id进行了分片, 实际工作中还会经常按业务字段分片, 这次有tb3表, 按user_id分片, 依上文思路, 先调整下涉及到的配置文件.
 
1. 在schema.xml中, 添加tb3表的配置.
 
      <table name="tb3" dataNode='dnTest1,dnTest2' rule="mod-long-user_id"/>
 
2. 在rule.xml中, 添加tb3表分片配置, 其中分片算法还是简单取摸.
 
      <tableRule name="mod-long-user_id">
 
    <rule>
 
        <columns>user_id</columns>
 
        <algorithm>mod-long</algorithm>
 
    </rule>
 
</tableRule>
 
连接Mycat, 创建tb3的表结构.
 
mysql> create table tb3(id int auto_increment primary key, user_id int not null default 0, user_name varchar(30) not null default '');
 
下面插入2条数据.
 
mysql> insert into tb3(id, user_id, user_name) values(7, 1, 'abcd');
 
mysql> insert into tb3(id, user_id, user_name) values(7, 2, 'efgh');
 
查看发现, 虽然id字段为主键, 但在分片情况下, 其已失去了原有的唯一性约束. 原因很简单, 多个MySQL实例上唯一主键可以很自然的出现相同值.
 
mysql> select * from tb3;
 
+----+---------+-----------+
 
| id | user_id | user_name |
 
+----+---------+-----------+
 
|  7 |       2 | efgh      |
 
|  7 |       1 | abcd      |
 
+----+---------+-----------+
 
针对上述情况, Mycat中使用全局序列号(简称sequence), 来重塑主键的全局唯一性, 提供了包含本地配置和数据库配置等多种实现方式.
 
下面使用配置数据库的方式来获取sequence, 先了解下其原理.
 
在数据库中创建一张表, 存放sequence名称(name列), 当前值(current_value), 和步长(increment, 表每次读取多少个sequence).
 
sequence的获取, 和维护:
 
1). 当初次使用该sequence时, 根据传入的sequence名称, 从数据库该表中读取current_value, 和increment到Mycat中, 并将数据库中的current_value设置为原current_value值+increment值.
 
2). Mycat将读取到current_value值+increment值作为本次要使用的sequence值, 下次再使用时, 自动加1, 当使用increment次后, 执行步骤1)相同的操作.
 
3). Mycat负责维护这张表, 用到哪些sequence, 只需在该表中插入一条记录即可. 若某次读取的sequence没有用完, Mycat就停掉了, 则这次读取的sequence剩余值不会再使用.
 
配置方式:
 
1. 在server.xml中, 开启使用数据库方式生成sequence的开关.
 
<property name="sequnceHandlerType">1</property>
 
2. 调整schema.xml, 并在Mycat后端某个MySQL实例上创建mycatseq数据库(该库名随意), MYCAT_SEQUENCE表(表名要大写), 和3个函数.
 
2.1 于schema.xml中添加如下配置.
 
<dataNode name="gseq" dataHost="Rep1_3306" database="mycatseq"/>
 
2.2 登陆节点主机Rep1_3306创建相应的数据库和表.
 
mysql> create database mycatseq;
 
mysql> use mycatseq;
 
mysql> create table MYCAT_SEQUENCE(name varchar(50) not null, current_value int not null, increment int not null default 100, primary key(name));
 
2.3 并创建3个函数.
 
# mycat_seq_currval
 
DELIMITER //
 
CREATE DEFINER=`zzzz`@`192.168.4.%` FUNCTION `mycat_seq_currval`(seq_name VARCHAR(50)) RETURNS varchar(64) CHARSET utf8 COLLATE utf8_bin
 
    DETERMINISTIC
 
BEGIN
 
        DECLARE retval VARCHAR(64);
 
        SET retval="-999999999,null";
 
        SELECT concat(CAST(current_value AS CHAR),",",CAST(increment AS CHAR) ) INTO retval   FROM MYCAT_SEQUENCE  WHERE name = seq_name;
 
        RETURN retval;
 
END; //
 
DELIMITER ;
 
# mycat_seq_nextval;
 
DELIMITER //
 
CREATE DEFINER=`zzzz`@`192.168.4.%` FUNCTION `mycat_seq_nextval`(seq_name VARCHAR(50)) RETURNS varchar(64) CHARSET utf8 COLLATE utf8_bin
 
    DETERMINISTIC
 
BEGIN
 
         UPDATE MYCAT_SEQUENCE
 
                 SET current_value = current_value + increment  WHERE name = seq_name;
 
         RETURN mycat_seq_currval(seq_name);
 
END; //
 
DELIMITER ;
 
# mycat_seq_setval;
 
DELIMITER //
 
CREATE DEFINER=`zzzz`@`192.168.4.%` FUNCTION `mycat_seq_setval`(seq_name VARCHAR(50), value INTEGER) RETURNS varchar(64) CHARSET utf8 COLLATE utf8_bin
 
    DETERMINISTIC
 
BEGIN
 
         UPDATE MYCAT_SEQUENCE
 
                   SET current_value = value
 
                   WHERE name = seq_name;
 
         RETURN mycat_seq_currval(seq_name);
 
END; //
 
DELIMITER ;
 
至此, 使用Mycat sequence的准备工作就绪了, 谁来使用呢, 就是tb3, 怎么使用呢, 看如下步骤.
 
1. 要在schema.xml中对tb3的配置稍微改造下, 添加autoIncrement="true", 告诉Mycat tb3使用sequence; 添加primaryKey="id", 告诉Mycat主键字段是什么.
 
<table name="tb3" dataNode='dnTest1,dnTest2' rule="mod-long-user_id" primaryKey="id" autoIncrement="true"/>
 
2. 那Mycat如何知道去哪个节点主机获取sequence呢, 需要在一个新的配置文件sequence_db_conf.properties中标明表名(要大写)和分片节点的对应关系.
 
#testdb
 
TB3=gseq
 
3. 登陆节点主机Rep1_3306, 初始化tb3表的sequence.
 
mysql> insert into MYCAT_SEQUENCE(name, current_value, increment) values('TB3', 400, 100);
 
mysql> select * from MYCAT_SEQUENCE;
 
+------+---------------+-----------+
 
| name | current_value | increment |
 
+------+---------------+-----------+
 
| TB3  |           400 |       100 |
 
+------+---------------+-----------+
 
登陆Mycat, 验证sequence可以正常使用.
 
mysql> select next value for MYCATSEQ_TB3;
 
+-----+
 
| 500 |
 
+-----+
 
| 500 |
 
+-----+
 
此时, tb3表使用sequence的工作准备好了, 下面插入数据看看.
 
mysql> insert into tb3(user_name) values('igkl');
 
ERROR 1064 (HY000): bad insert sql (sharding column:USER_ID not provided,INSERT INTO tb3 (ID, user_name)
 
VALUES (501, 'igkl')
 
mysql> insert into tb3(id, user_id, user_name) values(9, 4, 'igkl');
 
由于Mycat负责主键值id的生成, SQL语句中可省去id字段不写(若像上面, 指定id为某值, 也没问题).
 
mysql> insert into tb3(user_id, user_name) values(59, 'mnop');
 
mysql> select * from tb3 where user_id = 59;
 
+-----+---------+-----------+
 
| id  | user_id | user_name |
 
+-----+---------+-----------+
 
| 502 |      59 | mnop      |
 
+-----+---------+-----------+
 
查看日志, 发现Mycat对原始SQL语句进行了改写, 添加了id字段.
 
03/18 20:46:36.798  DEBUG [$_NIOREACTOR-1-RW] (ServerQueryHandler.java:56) -ServerConnection [id=1, schema=testdb, host=192.168.4.184, user=test_user,txIsolation=3, autocommit=true, schema=testdb]insert into tb3(user_id, user_name) values(59, 'mnop')
 
03/18 20:46:36.800  DEBUG [Thread-1] (NonBlockingSession.java:113) -ServerConnection [id=1, schema=testdb, host=192.168.4.184, user=test_user,txIsolation=3, autocommit=true, schema=testdb]insert into tb3(ID,user_id, user_name) values( 502,59, 'mnop'), route={
 
   1 -> dnTest2{insert into tb3(ID,user_id, user_name) values( 502,59, 'mnop')}
 
03/18 20:46:36.800  DEBUG [Thread-1] (MySQLConnection.java:459) -con need syn ,total syn cmd 2 commands SET names utf8;SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;schema change:false con:MySQLConnection [id=2, lastTime=1521377196800, user=zzzz, schema=test2, old shema=test2, borrowed=true, fromSlaveDB=false, threadId=81, charset=utf8, txIsolation=0, autocommit=true, attachment=dnTest2{insert into tb3(ID,user_id, user_name) values( 502,59, 'mnop')}, respHandler=SingleNodeHandler [node=dnTest2{insert into tb3(ID,user_id, user_name) values( 502,59, 'mnop')}, packetId=0], host=192.168.4.151, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted=true]
 
03/18 20:46:36.802  DEBUG [$_NIOREACTOR-2-RW] (NonBlockingSession.java:229) -release connection MySQLConnection [id=2, lastTime=1521377196792, user=zzzz, schema=test2, old shema=test2, borrowed=true, fromSlaveDB=false, threadId=81, charset=utf8, txIsolation=3, autocommit=true, attachment=dnTest2{insert into tb3(ID,user_id, user_name) values( 502,59, 'mnop')}, respHandler=SingleNodeHandler [node=dnTest2{insert into tb3(ID,user_id, user_name) values( 502,59, 'mnop')}, packetId=1], host=192.168.4.151, port=3306, statusSync=null, writeQueue=0, modifiedSQLExecuted=true]

(编辑:财气旺网 - 财气网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!