前言:
使用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)