MyCat 主鍵ID自增長配置


  在實現分庫分表的情況下,數據庫自增主鍵已無法保證自增主鍵的全局唯一。為此,MyCat 提供了全局sequence,並且提供了包含本地配置和數據庫配置等多種實現方式,實現方式主要有三種:本地文件方式數據庫方式本地時間戳算法。

  一、本地文件方式

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

    譬如:    

#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

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

   2、配置sequence_conf.properties  

$ vim mycat/conf/sequence_conf.properties
#default global sequence

GLOBAL.HISIDS=
GLOBAL.MINID=10001
GLOBAL.MAXID=20000
GLOBAL.CURID=10000

    設置完成以后重啟MyCat

  3、測試 

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;

    

#此時,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)等信息;   

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,表示使用數據庫方式。
<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中創建。   

--  創建MYCAT_SEQUENCE表
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;
-- – 獲取當前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記錄

-- 插入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。
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、開始測試

    

$ 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 |
+-----+--------------+-----------+----------+

    錯誤處理: 

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必須大寫。

 

  三、本地時間戳算法

    待續。。。

    

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM