zoukankan      html  css  js  c++  java
  • MyCat 主键ID自增长配置

      在实现分库分表的情况下,数据库自增主键已无法保证自增主键的全局唯一。为此,MyCat 提供了全局sequence,并且提供了包含本地配置和数据库配置等多种实现方式,实现方式主要有三种:本地文件方式数据库方式本地时间戳算法。

      一、本地文件方式

        原理:此方式MyCAT将sequence配置到文件中,当使用到sequence中的配置后,MyCAT会更下conf中的sequence_conf.properties文件中sequence当前的值。

        譬如:    

    1
    2
    3
    4
    5
    6
    7
    #default global sequence
     
    GLOBAL.HISIDS=
    GLOBAL.MINID=10001
    GLOBAL.MAXID=20000
    GLOBAL.CURID=10000
    #其中HISIDS表示使用过的历史分段(一般无特殊需要可不配置),MINID表示最小ID值,MAXID表示最大ID值,CURID表示当前ID值。

       使用方式:

       1、配置MyCat的Server.xml

    1
    2
    3
    4
    # 其中0,表示使用本地文件方式。
    <system>
        <property name="sequnceHandlerType">0</property>
    </system>

       2、配置sequence_conf.properties  

    1
    2
    3
    4
    5
    6
    7
    $ vim mycat/conf/sequence_conf.properties
    #default global sequence
     
    GLOBAL.HISIDS=
    GLOBAL.MINID=10001
    GLOBAL.MAXID=20000
    GLOBAL.CURID=10000

        设置完成以后重启MyCat

      3、测试 

    1
    2
    3
    4
    5
    mysql> create table test(id int,name varchar(20));
     
    mysql> insert into test(id,name) values(next value for MYCATSEQ_GLOBAL,@@hostname);
     
    mysql> select * from test;

        

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #此时,sequence_conf.properties中GLOBAL.CURID值为10001。当然,可以使用sequence_conf.properties中定义的任何规则,譬如:
    # self define sequence
     
    COMPANY.HISIDS=
    COMPANY.MINID=1001
    COMPANY.MAXID=2000
    COMPANY.CURID=1000
     
    # COMPANY 就是要使用自增的配置,在这里也可以使用其他的名字,但必须是大写的;定义以后可以在全局使用。
     
    #可以使用 mysql>select next value for MYCATSEQ_xxx(自定义的名字); 来查看下一个自增ID。

      二、数据库方式   

        原理:在数据库中建立一张表,存放sequence名称(name),sequence当前值(current_value),步长(increment int类型每次读取多少个sequence,假设为K)等信息;   

    1
    2
    3
    4
    5
    Sequence获取步骤:
      1).第一次使用该sequence时,根据传入的sequence名称,从数据库这张表中读取current_value,和increment到MyCat中,并将数据库中的current_value设置为原current_value值+increment值(实现方式是基于后续的存储函数)
     
      2).MyCat将读取到current_value+increment作为本次要使用的sequence值,下次使用时,自动加1,当使用increment次后,执行步骤1)相同的操作. 
           MyCat负责维护这张表,用到哪些sequence,只需要在这张表中插入一条记录即可。若某次读取的sequence没有用完,系统就停掉了,则这次读取的sequence剩余值不会再使用。   

      

        使用方式:

       1、配置Server.xml

    1
    2
    3
    4
    # 其中1,表示使用数据库方式。
    <system>
        <property name="sequnceHandlerType">1</property>
    </system>

       2、在其中一个分片点对应的数据库中创建表和存储过程

          因我在schema.xml 中配置的是: <dataNode name="dn$1-4" dataHost="localhost1" database="db$1-4" />

           譬如我在dn2中创建,对应的数据库名为db2(为什么这里会涉及到datanode,因为后续的sequence_db_conf.properties文件会使用到),

          注意,是登录到数据库中创建,

          而不是在mycat中创建。   

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    --  创建MYCAT_SEQUENCE表<br>CREATE TABLE MYCAT_SEQUENCE (
    `name` VARCHAR(50) NOT NULL,
    current_value INT NOT NULL,
    increment INT NOT NULL DEFAULT 1,
    remark varchar(100),  -- remark 并不是必须的,在这里我是为了让每一个表都对应一个全局的自增,在Remark中配置自增项对应的表名。方便后期维护
    PRIMARY KEY(name)) ENGINE=InnoDB;
    <br>-- – 获取当前sequence的值(返回当前值,增量)
    DROP FUNCTION IF EXISTS `mycat_seq_currval`;
    DELIMITER ;;
    CREATE DEFINER=`root`@`%` FUNCTION `mycat_seq_currval`(seq_name VARCHAR(50)) RETURNS varchar(64) CHARSET latin1
    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 ;
     
    -- 设置sequence值
    DROP FUNCTION IF EXISTS `mycat_seq_nextval`;
    DELIMITER ;;
    CREATE DEFINER=`root`@`%` FUNCTION `mycat_seq_nextval`(seq_name VARCHAR(50)) RETURNS varchar(64) CHARSET latin1
    DETERMINISTIC
    BEGIN
    UPDATE MYCAT_SEQUENCE
    SET current_value = current_value + increment WHERE name = seq_name;
    RETURN mycat_seq_currval(seq_name);
    END
    ;;
    DELIMITER ;
    -- 获取下一个sequence值
    DROP FUNCTION IF EXISTS `mycat_seq_setval`;
    DELIMITER ;;
    CREATE DEFINER=`root`@`%` FUNCTION `mycat_seq_setval`(seq_name VARCHAR(50), value INTEGER) RETURNS varchar(64) CHARSET latin1
    DETERMINISTIC
    BEGIN
    UPDATE MYCAT_SEQUENCE
    SET current_value = value
    WHERE name = seq_name;
    RETURN mycat_seq_currval(seq_name);
    END
    ;;
    DELIMITER ; 

          在表MYCAT_SEQUENCE中,其中:

           – name sequence名称
                 – current_value 当前value
                 – increment增长步长! 可理解为mycat在数据库中一次读取多少个sequence. 当这些用完后, 下次再从数据库中读取.

            注意:MYCAT_SEQUENCE必须大写。

           创建存储函数:

            注意:必须在同一个数据库中创建,在本例中,是db2。一共要创建三个。

            – 获取当前sequence的值(返回当前值,增量)

        3、  插入sequence记录

    1
    2
    3
    4
    5
    -- 插入sequence记录
    INSERT INTO MYCAT_SEQUENCE(name,current_value,increment,remark) VALUES ('DICT', 1, 100,'match:tb_dic');
     
    INSERT INTO MYCAT_SEQUENCE(name,current_value,increment,remark) VALUES ('GLOBAL', 1, 100,'GLOBAL');
    -- 代表插入了一个名为mycat的sequence,当前值为1,步长为100。
    1
    2
    3
    4
    5
    6
    7
    mysql> select * from mycat_sequence;
    +----------------+---------------+-----------+--------------------------------+
    | name           | current_value | increment | remark                         |
    +----------------+---------------+-----------+--------------------------------+
    | DICT           |             1 |       100 | match:tb_dic                   |
    | GLOBAL         |           200 |       100 | GLOBAL                         |
    +----------------+---------------+-----------+--------------------------------+

      

        至此,数据库方面的准备工作已结束完毕。

      4、设置 sequence_db_conf.properties

         在mycat conf目录下的sequence_db_conf.properties文件中添加如下内容:DICT=dn3 dn3:表示我把表和函数都建在了dn3节点上

         注意:DICT必须为大写,这个与表的数据是否大写无关,事实上,MYCAT_SEQUENCE中name是否大小写对结果没有影响。

           重启MyCat  

      5、开始测试

        

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    $ mysql -h127.0.0.1 -utest -ptest -P8066 -DTESTDB
    mysql>
    create table tb_dic
    (
       id                   int not null auto_increment,
       dic_name             varchar(100) not null comment '字典名称',
       dic_value            varchar(20) not null comment '字典值',
       dic_type             int not null comment '字典类型: 如果是类型,如支付方式等',
       primary key (id)
    );
    # 然后插入值
    mysql>  INSERT into tb_dic(id,dic_name,dic_value,dic_type) VALUES(next value for MYCATSEQ_DICT,'支付方式','1',0);
    +-----+--------------+-----------+----------+
    | id  | dic_name     | dic_value | dic_type |
    +-----+--------------+-----------+----------+
    | 101 | 活动形式      | 2         |        0 |
    | 102 | 表单类型      | 2         |        0 |
    +-----+--------------+-----------+----------+

        错误处理: 

    1
    ERROR 1003 (HY000): mycat sequnce err.org.opencloudb.config.util.ConfigException: can't find definition for sequence :DICT

        因为对于sequence_db_conf.properties的修改当前的mycat并不知晓,这时候,可重启mycat或者登录9066管理端口进行 reload @@config;

        至此,测试完毕,关键还是两点:MYCAT_SEQUENCE必须大写,sequence_db_conf.properties文件中DICT=dn3必须大写。

      三、本地时间戳算法

        待续。。。

        

      

  • 相关阅读:
    TCP和UDP的主要特点
    C++ this和*this的区别
    C++空类中含有哪些默认的函数
    const关键字的用途
    哪些函数不能成为虚函数?
    C++是不是类型安全带的?
    多线程 测试
    多线程 采用三个线程 依次数到75
    多线程 实现控制台打印“我爱你”10遍
    多线程 创建子父线程 保证一件事 子线程执行三次后 父线程执行5次 循环10次
  • 原文地址:https://www.cnblogs.com/jpfss/p/8194617.html
Copyright © 2011-2022 走看看