1. 程式人生 > >Mycat之資料庫主鍵自增長(資料庫增長的方式)-yellowcong

Mycat之資料庫主鍵自增長(資料庫增長的方式)-yellowcong

我們先來通過mycat實現一個自增長的主鍵,現在有兩個資料庫,mycat和mycat2,然後設定資料庫增長的方式,按照自增長的方式實現。自增長實現步驟:1、建立資料庫,2、建立mycat的自增長函式,3、插入需要自增長策略,4、配置schemal.xml,新增自增長的表,5、配置server.xml,設定主鍵增長策略,6、配置sequence_db_conf.properties,新增需要自增長的表。 如果我們後期想新增自增長的表,只需要進行步驟3、4、6 三個步驟。

資料準備

1、建立資料庫

建立兩個資料庫,並都建立test表

#建立資料庫
create database
mycat;
#新增表 use mycat #建立表test create table test3(id int auto_increment primary key,name varchar(32)) ; #建立資料庫 create database mycat3; #新增表 use mycat 2 #建立表test create table test3(id int auto_increment primary key,name varchar(32)) ;

這裡寫圖片描述

新增後的表資料,看了一下,表示表建立好了
這裡寫圖片描述

2、建立Mycat生成唯一主鍵所需要的函式

我將自增長的函式都建立在了mycat這個db中

DROP TABLE IF EXISTS MYCAT_SEQUENCE;
CREATE TABLE MYCAT_SEQUENCE (
NAME VARCHAR (50) NOT NULL,
current_value INT NOT NULL,
increment INT NOT NULL DEFAULT 100,
PRIMARY KEY (NAME)
) ENGINE = INNODB ;


INSERT INTO MYCAT_SEQUENCE(NAME,current_value,increment) VALUES ('GLOBAL', 100000, 100);

DROP FUNCTION IF
EXISTS `mycat_seq_currval`;
DELIMITER ;; CREATE FUNCTION `mycat_seq_currval`(seq_name VARCHAR(50)) RETURNS VARCHAR(64) CHARSET utf8 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 ; DROP FUNCTION IF EXISTS `mycat_seq_nextval`; DELIMITER ;; CREATE FUNCTION `mycat_seq_nextval`(seq_name VARCHAR(50)) RETURNS VARCHAR(64) CHARSET utf8 DETERMINISTIC BEGIN UPDATE MYCAT_SEQUENCE SET current_value = current_value + increment WHERE NAME = seq_name; RETURN mycat_seq_currval(seq_name); END ;; DELIMITER ; DROP FUNCTION IF EXISTS `mycat_seq_setval`; DELIMITER ;; CREATE FUNCTION `mycat_seq_setval`(seq_name VARCHAR(50), VALUE INTEGER) RETURNS VARCHAR(64) CHARSET utf8 DETERMINISTIC BEGIN UPDATE MYCAT_SEQUENCE SET current_value = VALUE WHERE NAME = seq_name; RETURN mycat_seq_currval(seq_name); END ;; DELIMITER ;

3、測試新增結果

#查詢當前所在db ,這個語句只是想給大家證明,我是在mycat 這個資料庫裡面新增的函式
select database();

#查詢doubi這張表裡面的資料
select mycat_seq_nextval('doubi');

這裡寫圖片描述

4、插入要自增的表名稱到MYCAT_SEQUENC表

插入資料的時候,一定要注意,自己需要插入的表,一定要是大寫的

#設定TEST3表的增長方式為 步進為1 ,
insert into MYCAT_SEQUENCE (name,current_value,increment) values ('TEST3',0,1);

#查詢結果
 select * from MYCAT_SEQUENCE;

這裡寫圖片描述

配置maycat

1、配置schemal.xml

vim conf/schemal.xml, 資料庫的表名稱為test2,設定表的主鍵,這樣mycat好給我們生成主鍵,而且我們是自增長,所以需要配置autoIncrement="true",這個裡面 type="global" 表示是全域性的表, 每個子節點,都會存在

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

        <schema name="yellowcong" checkSQLschema="true" sqlMaxLimit="1000">
                <table name="test3" dataNode="jdbc_node1,jdbc_node2" primaryKey="id" autoIncrement="true"  type="global"/>
        </schema>

        <dataNode name="jdbc_node1" dataHost="localhost" database="mycat" />
        <dataNode name="jdbc_node2" dataHost="localhost" database="mycat2" />

        <dataHost name="localhost" maxCon="1000" minCon="10" balance="0"
                          writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>

                <writeHost host="hostM1" url="127.0.0.1:3306" user="root" password="root" />

        </dataHost>


</mycat:schema>

2、配置server.xml

需要修改sequnceHandlerType 為1,<property name="sequnceHandlerType">1</property>

vim conf/server.xml

0 表示是表示使用本地檔案方式。
1 表示的是根據資料庫來生成,就是我們自己配置的自增長
2 表示時間戳的方式 ID= 64 位二進位制 (42(毫秒)+5(機器 ID)+5(業務編碼)+12(重複累加)
<property name="sequnceHandlerType">1</property>

下面是全部配置

<?xml version="1.0" encoding="UTF-8"?>
<!-- - - Licensed under the Apache License, Version 2.0 (the "License");
        - you may not use this file except in compliance with the License. - You
        may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0
        - - Unless required by applicable law or agreed to in writing, software -
        distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT
        WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the
        License for the specific language governing permissions and - limitations
        under the License. -->
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://io.mycat/">
        <system>
        <property name="serverPort">8066</property>
        <property name="useSqlStat">0</property>  <!-- 1為開啟實時統計、0為關閉 -->
        <property name="useGlobleTableCheck">0</property>  <!-- 1為開啟全加班一致性檢測、0為關閉 -->

                <property name="sequnceHandlerType">1</property>

                <!--預設為type 0: DirectByteBufferPool | type 1 ByteBufferArena-->
                <property name="processorBufferPoolType">0</property>

                <!--分散式事務開關,0為不過濾分散式事務,1為過濾分散式事務(如果分散式事務內只涉及全域性表,則不過濾),2為不過濾分散式事務,但是記錄分散式事務日誌-->
                <property name="handleDistributedTransactions">0</property>

                        <!--
                        off heap for merge/order/group/limit      1開啟   0關閉
                -->
                <property name="useOffHeapForMerge">1</property>

                <!-- 單位為m-->
                <property name="memoryPageSize">1m</property>

                <!--單位為k -->
                <property name="spillsFileBufferSize">1k</property>

                <property name="useStreamOutput">0</property>

                <!--單位為m-->
                <property name="systemReserveMemorySize">384m</property>


                <!--是否採用zookeeper協調切換  -->
                <property name="useZKSwitch">true</property>
        </system>

        <user name="root">
                <property name="password">root</property>
                <property name="schemas">yellowcong</property>
        </user>

        <user name="user">
                <property name="password">user</property>
                <property name="schemas">yellowcong</property>
                <property name="readOnly">true</property>
        </user>

</mycat:server>

3、配置sequence_db_conf.properties

#配置預設的表自增長設定
vim ./conf/sequence_db_conf.properties

#新增需要自增長的表名稱
TEST3=jdbc_node1

這裡寫圖片描述

測試插入資料

重啟mycat服務後,連線資料庫,測試插入資料到TEST3表

#連線mycat
mysql -h 127.0.0.1 -P 8066 -u root -proot

#使用yellowocng 資料庫
use yellowcong ;

#查看錶資訊
show tables ;

#插入資料
#插入多條資料
insert into test3 (name) values ('doubi1'),('doubi2'),('doubi3'),('yellowcong');

#查詢資料
select * from test3;

這裡寫圖片描述

查詢資料,結果可以看到,角標的增長很完美。是增長的步進是1.
這裡寫圖片描述

檢視子節點,可以看到對mycat操作後,由於是全域性表,所以每個子節點資料中,都存在表資訊。
這裡寫圖片描述

錯誤集合

ERROR 1064 (HY000): bad insert sql (sharding column:ID not provided,INSERT INTO test2 (NULL, ‘doubi1’)

包這個問題的原因很明顯,就是我們沒有設定mycat中虛擬表的id自增,所以導致沒有獲取到id,所以導致了這個問題。

這裡寫圖片描述

#修改後的語句
insert into test2(name) values('doubi1'),('doubi2'),('doubi3'),('yellowcong');

ERROR 1064 (HY000): insert must provide ColumnList

必須提供新增的列,直接插入,導致了問題,所以我們需要修該插入語句
這裡寫圖片描述

#原來語句
insert into test2 (null,'doubi1'),(null,'doubi2'),(null,'doubi3'),(null,'yellowcong');

#修改後的語句
insert into test2(name) values('doubi1'),('doubi2'),('doubi3'),('yellowcong');

Out of range value for column ‘id’ at row 1

導致這個問題的大致原因可能是由於mycat生成的id和資料庫的字元長度對不上,超過了資料庫配置的預設長度所導致的。解決辦法,就是修改數server.xml,設定id生成策略是根據資料庫生成的。
這裡寫圖片描述

vim conf/server.xml

0 表示是表示使用本地檔案方式。
1 表示的是根據資料庫來生成
2 表示時間戳的方式 ID= 64 位二進位制 (42(毫秒)+5(機器 ID)+5(業務編碼)+12(重複累加)
<property name="sequnceHandlerType">1</property>

這裡寫圖片描述

mycat sequnce err.io.mycat.config.util.ConfigException: can’t find definition for sequence :TEST2

mycat對應sequence_db_conf.properties增加相應設定
這裡寫圖片描述

#配置預設的表自增長設定
vim ./conf/sequence_db_conf.properties

#新增需要自增長的表名稱
TEST3=jdbc_node1

這裡寫圖片描述

mycat sequnce err.java.lang.RuntimeException: can’t fetch sequnce in db,sequnce :TEST2

報錯,說沒辦法獲取到 id,從資料庫中,這個說明我們sequence_db_conf.properties 的配置檔案有問題
這裡寫圖片描述

mycat sequnce err.java.lang.RuntimeException: can’t fetch sequnce in db,sequnce :TEST2 detail:FUNCTION mycat.mycat_seq_nextval does not exist

說沒有mycat.mycat_seq_nextval 這個函式,說明在rule.xml中還需要新增這個配置
這裡寫圖片描述

#新增表
DROP TABLE IF EXISTS MYCAT_SEQUENCE;
CREATE TABLE MYCAT_SEQUENCE (
NAME VARCHAR (50) NOT NULL,
current_value INT NOT NULL,
increment INT NOT NULL DEFAULT 100,
PRIMARY KEY (NAME)
) ENGINE = INNODB ;


INSERT INTO MYCAT_SEQUENCE(name,current_value,increment) VALUES ('GLOBAL', 100000, 100);

DROP FUNCTION IF EXISTS `mycat_seq_currval`;
DELIMITER ;;
CREATE FUNCTION `mycat_seq_currval`(seq_name VARCHAR(50)) 
RETURNS varchar(64) CHARSET utf8
    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 ;

DROP FUNCTION IF EXISTS `mycat_seq_nextval`;
DELIMITER ;;
CREATE FUNCTION `mycat_seq_nextval`(seq_name VARCHAR(50)) RETURNS varchar(64)
 CHARSET utf8
    DETERMINISTIC
BEGIN UPDATE MYCAT_SEQUENCE  
                 SET current_value = current_value + increment 
                  WHERE name = seq_name;  
         RETURN mycat_seq_currval(seq_name);  
END
;;
DELIMITER ;


DROP FUNCTION IF EXISTS `mycat_seq_setval`;
DELIMITER ;;
CREATE FUNCTION `mycat_seq_setval`(seq_name VARCHAR(50), value INTEGER) 
RETURNS varchar(64) CHARSET utf8
    DETERMINISTIC
BEGIN UPDATE MYCAT_SEQUENCE  
                   SET current_value = value  
                   WHERE name = seq_name;  
         RETURN mycat_seq_currval(seq_name);  
END
;;
DELIMITER ;




#插入一條資料,這條資料是我們這個表所需要的。
#必須是大寫的字元,不然就會報錯
#插入需要自增張的表的策略
insert into  MYCAT_SEQUENCE (name,current_value,increment) values ('TEST3',0,1);

參考文章