前言:
使用MyCat的朋友应该有很大一部分是要做sharding的,而拆分面临的很大一个问题就是全局自增序列没有了。MyCat的开发人员早就考虑到了这一点,并提供了实现全局自增序列的方案,实现方式大概有“本地文件”、“数据库”、“本地时间戳”、“catlet注解”、“zookeeper”、“last_insert_id”这几种。每种方式可能都有自己的优缺点,要根据自己的实际情况选用。如果自己有第三方的全局序列方案更优,就不要用MyCat的方案了。MyCat中文档比较详细,并且实现起来比较靠谱的是数据库方式。下面的文档就只讨论数据库方式,基于MyCat1.6稳定版。实现原理:
在数据库中创建一张table和几个function,记录需要自增值的表名、目前的自增值、步长,当需要新的自增值时,操作此表即可。注意事项:
1.若某次读取的sequence没有用完系统就宕机了,则本地已经读取并且未使用的sequence会被丢弃。2.改造之后,要检查线上环境insert into语句的兼容性,例如insert into table(id) values();这种可能就不被支持。
配置过程:
1.在server.xml中把生成全局序列的方式改为数据库方式1sequnceHandlerType配置为1,就是使用数据库方式生成sequence。
2.在一个指定的数据库中创建指定的sequence表,并插入数据。
点击(此处)折叠或打开
-
CREATE TABLE `MYCAT_SEQUENCE` (
-
`name` varchar(50) NOT NULL,
-
`current_value` int(11) NOT NULL,
-
`increment` int(11) NOT NULL DEFAULT '1',
-
PRIMARY KEY (`name`)
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
-
-
insert into MYCAT_SEQUENCE(name,current_value,increment) values('DATETIME_TEST',1,1);
数据库不需要和生产DB混在一起,独立出来最好,但是注意别放到异地,同一交换机(网段)内即可。否则并发获取自增值时性能无法保证。
创建时直接到后端的MySQL上创建,不要在MyCat中创建,因为schema.xml中如果没配置此表,创建会报错。
3.在同一台机器上创建相关的几个function
同上,直接在后端指定的MySQL上创建即可。数据库记得打开log_bin_trust_function_creators=1的选项。
点击(此处)折叠或打开
-
#取当前squence的值
-
DROP FUNCTION IF EXISTS mycat_seq_currval;
-
DELIMITER $$
-
CREATE FUNCTION 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 $$
-
CREATE FUNCTION 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 $$
-
CREATE FUNCTION 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 ;
4.配置数据表(需要使用全局序列的)从哪里读取全局序列
点击(此处)折叠或打开
- root# vim conf/sequence_db_conf.properties
- 增加DATETIME_TEST=dn8
dn8即是在schema.xml中配置的datanode节点。这个节点就是刚刚我们创建MYCAT_SEQUENCE表的节点。
5.配置MYCAT_SEQUENCE表的datanode,和需要使用全局序列的表的自增属性
点击(此处)折叠或打开
- schema name="xxx" checkSQLschema="false">
-
table name="datetime_test" primaryKey="id" autoIncrement="true" dataNode="dn3,dn4,dn5,dn6,dn7"
- rule="sharding-by-date" />
-
-
/schema>
-
-
-
dataNode name="dn3" dataHost="master_server" database="db0" />
-
dataNode name="dn4" dataHost="master_server" database="db1" />
-
dataNode name="dn5" dataHost="master_server" database="db2" />
-
dataNode name="dn6" dataHost="master_server" database="db3" />
-
dataNode name="dn7" dataHost="master_server" database="db4" />
-
dataNode name="dn8" dataHost="sequence_server" database="sequence_db" />
-
-
-
dataHost name="master_server" maxCon="1000" minCon="10" balance="0"
-
writeType="0" dbType="mysql" dbDriver="native" switchType="-1" slaveThreshold="100">
-
heartbeat>show slave status/heartbeat>
-
!-- can have multi write hosts -->
- writeHost host="hostM1" url="vip:3306" user="xxx" password="xxx" />
- /dataHost>
-
-
dataHost name="sequence_server" maxCon="1000" minCon="10" balance="0"
-
writeType="0" dbType="mysql" dbDriver="native" switchType="-1" slaveThreshold="100">
-
heartbeat>select user()/heartbeat>
-
!-- can have multi write hosts -->
-
writeHost host="hostM1" url="vip:3306" user="xxx" password="xxx" />
- /dataHost>
MyCat中执行reload @@config;
7.进行测试
点击(此处)折叠或打开
-
#在MyCat中插入一组数据,然后查看全局自增是否生效
- mysql> insert into datetime_test(create_time) values('2017-01-02 00:00:00'),('2017-01-03 00:00:00'),('2017-01-04 00:00:00'),('2017-01-05 00:00:00'),('2017-01-06 00:00:00'),('2017-01-07 00:00:00'),('2017-01-08 00:00:00'),('2017-01-09 00:00:00'),('2017-01-10 00:00:00');
-
-
mysql> select * from datetime_test;
+----+---------------------+
| id | create_time |
+----+---------------------+
| 2 | 2017-01-01 00:00:00 |
| 3 | 2017-01-02 00:00:00 |
| 6 | 2017-01-05 00:00:00 |
| 11 | 2017-01-10 00:00:00 |
| 7 | 2017-01-06 00:00:00 |
| 5 | 2017-01-04 00:00:00 |
| 10 | 2017-01-09 00:00:00 |
| 8 | 2017-01-07 00:00:00 |
| 4 | 2017-01-03 00:00:00 |
| 9 | 2017-01-08 00:00:00 |
+----+---------------------+
10 rows in set (0.01 sec)