1、原理
在数据库中建立一张表,存放“名称”,“当前值”,“步长”(mycat 每次读取多少个 sequence)
sequence 获取步骤:
1)当初次使用该sequence时,根据传入的squence名称,从这个表中获取current_value 和 increment 到mycat中,并将current_value 设置为current_value+increment
2)mycat 将本次读取到的current_value+increment 作为本次的squence,下次使用时自动加1,使用increment后,执行第一步操作。
3)mycat 维护这张张表,用到那些squence ,往表中插入一条数据即可。若某次读取的squence 没有用完服务器就停止,则读过的squence就不会再用,再从第一 步开始执行。
2 mycat配置:
1) server.xml
<property name="sequnceHandlerType">1</property>
配置为1 ,表示使用数据库方式生成squence
2) 创建数据库表(数据库表的位置 要和schema.xml 中指定的位置相同)
<table name="mycat_sequence" primaryKey="name" dataNode="dn1" />
也就是说 以下数据库表和function 的创建,需要在dn1 所在的节点上。
CREATE TABLE MYCAT_SEQUENCE (
NAME VARCHAR (50) NOT NULL comment "名称",
current_value INT NOT NULL comment "当前值",
increment INT NOT NULL DEFAULT 100 comment "步长",
PRIMARY KEY (NAME)
) ENGINE = INNODB ;
创建函数:
#取当前squence的值
DROP FUNCTION IF EXISTS mycat_seq_currval;
DELIMITER $$
CREATEFUNCTION mycat_seq_currval(seq_name VARCHAR(50))RETURNS VARCHAR(64) CHARSET `utf8`
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_setval;
DELIMITER $$
CREATEFUNCTION mycat_seq_setval(seq_name VARCHAR(50),VALUE INTEGER) RETURNS VARCHAR(64) CHARSET `utf8`
BEGIN
UPDATE MYCAT_SEQUENCE SET current_value = VALUE WHERE NAME = seq_name;
RETURN mycat_seq_currval(seq_name);
END$$
DELIMITER ;
#取下一个sequence的值
DROP FUNCTION IF EXISTS mycat_seq_nextval;
DELIMITER $$
CREATEFUNCTION mycat_seq_nextval(seq_name VARCHAR(50)) RETURNS VARCHAR(64) CHARSET `utf8`
BEGIN
UPDATE MYCAT_SEQUENCE SET current_value = current_value + increment
WHERE NAME = seq_name;
RETURN mycat_seq_currval(seq_name);
END$$
DELIMITER ;
插入一条初始化数据:
insert into MYCAT_SEQUENCE(name,current_value,increment) values('FILE_DATA_LCT_1',1000,10);
name 列 就是我们配置的全局序列号的名称。
如果需要多个全局序列号,可以初始化多条语句。
注意:
1、MYCAT_SEQUENCE 表和以上的 function,需要放在同一个节点上。这个结点就是sequence_db_conf.properties 指定的数据库结点
2、远程创建function失败,需要对数据库做如下设置:
/etc/my.cnf 下 my.ini
[mysqld]加上 log_bin_trust_function_creators=1
3)配置 sequence_db_conf.properties
指定自定义的全局序列号所在结点:
FILE_DATA_LCT_1=dn1
注意:必须大写(表名大写)
4)重新启动mycat
测试:
----登录到mycat 服务器
#mysql -h192.168.192.133 -utest -ptest -P8066 -DTESTDB
----查询出一个序列
mysql>SELECT next value for MYCATSEQ_FILE_DATA_LCT_1
其他使用方式:
insert intofile_data_lct_1(id,name) values(next value forMYCATSEQ_FILE_DATA_LCT_1,'test' );
以上方式 配置了一个全局序列号,插入数据的时候,可以通过 引用全局序列号获得一个 值,从而保证 多个分片id唯一。
如果主键id 是自增的,插入语句的时候,想要省略id ,
insert into
file_data_lct_1(name) values('test' );
类似这样,该怎么配置?
1)首先table1 表 主键id设置自增。
2)schema.xml 中配置 分片表 :
<table name="file_data_lct_1" primaryKey="id" autoIncrement="true" dataNode="dn1,dn2">
<table name="mycat_sequence" primaryKey="name" dataNode="dn1">
3)sequence_db_conf.properties 中增加相应表配置:
FILE_DATA_LCT_1=dn1
FILE_DATA_LCT_1是全局序列号的名字,正好也是表file_data_lct_1的大写方式。这不是巧合,mycat 故意这样设定的。
这样执行这条语句的时候 insert into file_data_lct_1(name) values('test' );
发现primaryKey ="id " 并且是自增的,就回去自动寻找 表名 大写对应 全局序列号是否存在,
如果不存在,直接报错。
如果存在,则 默默的获取到 FILE_DATA_LCT_1 的next value 作为 id 插入到 file_data_lct_1 中。