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);