[MyCAT]配置文件指定列值映射数据节点

11 篇文章 0 订阅
2 篇文章 0 订阅

需求

  • 可绑定数据源;
  • 通过配置文件指定。

建表语句:

create table cz_dept(id int auto_increment primary key , dept_no varchar(16) not null,dept_name varchar(32));

为演示mycat根据列值绑定数据源功能,以该表为例做演示,拆分键为dept_no

rule.xml

这个配置文件主要是进行规则信息的配置。
1.function标签:

<function name="hash-string"
			  class="io.mycat.route.function.PartitionByFileMap">
		<property name="mapFile">partition-hash-string.txt</property>
		<property name="type">1</property>
	</function>

首先这里制定了type,0表示数字类型的拆分键,为1表示拆分键为字符串类型。
上面的配置定义了一个名为hash-string的函数。
mapFile指向partition-hash-string.txt,这个文件实际保存了规则映射信息:

cn31101=0
cn31103=0
cn31105=0
cn31102=1

cn31101,cn31103,cn31105保存到0号节点,
cn31102保存到1号节点。

2.tableRule标签:

<tableRule name="hash-string">
		<rule>
			<columns>dept_no</columns>
			<algorithm>hash-string</algorithm>
		</rule>
	</tableRule>

此处指定拆分的列为dept_no,指定拆分的函数为上面定义的hash-string

schema.xml

这个配置文件主要是定义逻辑库中的逻辑表的信息。

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

	<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100" randomDataNode="dn1">
		<!-- auto sharding by id (long) -->
		<!--splitTableNames 启用<table name 属性使用逗号分割配置多个表,即多个表使用这个配置-->
		<table name="cz_dept" primaryKey="id" autoIncrement="true" dataNode="dn1,dn2" rule="hash-string"/>
		<table name="mycat_sequence" primaryKey="name" dataNode="dn1"/>
	</schema>
	<dataNode name="dn1" dataHost="localhost1" database="demo_1" />
	<dataNode name="dn2" dataHost="localhost1" database="demo_2" />
	<dataHost name="localhost1" 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="192.168.133.15:3306" user="pcloud"
				   password="pcloud">
		</writeHost>
	</dataHost>
</mycat:schema>

我提前在mysql创建了两个数据库,名为demo_1demo_2
逻辑库中主要创建的逻辑表是cz_dept,分布在dn1节点和dn2节点上,指向的拆分规则为hash-string。
注:在此处定义后,可连接到mycat执行sql语句建表。创建完以后到demo_1和demo_2数据库上面查看是否创建成功。

测试

根据上述配置文件的配置,cn31101、cn31103和cn31105会插入到0号节点,这里对应的也就是dn1节点;
cn31102会插入到dn2节点。

1.插入cn31101的数据

insert into cz_dept(dept_no,dept_name) values('cn31101','张三')
> Affected rows: 1
> 时间: 0.032s

手动连接到demo_1数据库进行查询:

select * from demo_1.cz_dept;

ID      DEPT_NO     DEPT_NAME
2	cn31101	       张三

确定数据已经插入到dn1节点。

2.插入cn31102的数据

insert into cz_dept(dept_no,dept_name) values('cn31102','李四')
> Affected rows: 1
> 时间: 0.014s

手动连接到demo_2数据库进行查询:

select * from demo_2.cz_dept;

ID      DEPT_NO     DEPT_NAME
3	cn31102	       李四

确定数据已经插入到dn2节点。

3.插入未维护的数据
这里插入cn38888的数据:

insert into cz_dept(dept_no,dept_name) values('cn38888','王二麻子')
> 1064 - can't find any valid datanode :CZ_DEPT -> DEPT_NO -> cn38888
> 时间: 0.012s

会提示没有该配置映射,插入失败。

注:这里可以将没有匹配的数据插入到默认节点,但根据医卫的场景,认为该场景不适合。如需要该配置可修改rule.xml,新增defaultNode配置:

<function name="hash-string"
			  class="io.mycat.route.function.PartitionByFileMap">
		<property name="mapFile">partition-hash-string.txt</property>
		<property name="type">1</property>
                <property name="defaultNode">0</property>
	</function>

关于mycat全局序列

上述用例中用了主键自增的id,这个如果直接使用并不能保证在分布式数据库环境生效,需要使用全局序列。
这个信息维护在表中,需要到某个mysql节点执行建表和创建触发器的函数:

DROP TABLE IF EXISTS MYCAT_SEQUENCE;
CREATE TABLE MYCAT_SEQUENCE (  name VARCHAR(64) NOT NULL,  current_value BIGINT(20) NOT NULL,  increment INT NOT NULL DEFAULT 1, PRIMARY KEY (name) ) ENGINE=InnoDB;

-- ----------------------------
-- Function structure for `mycat_seq_currval`
-- ----------------------------
DROP FUNCTION IF EXISTS `mycat_seq_currval`;
DELIMITER ;;
CREATE FUNCTION `mycat_seq_currval`(seq_name VARCHAR(64)) RETURNS varchar(64) CHARSET latin1
    DETERMINISTIC
BEGIN
    DECLARE retval VARCHAR(64);
    SET retval="-1,0";
    SELECT concat(CAST(current_value AS CHAR),",",CAST(increment AS CHAR) ) INTO retval FROM MYCAT_SEQUENCE  WHERE name = seq_name;
    RETURN retval ;
END
;;
DELIMITER ;

-- ----------------------------
-- Function structure for `mycat_seq_nextval`
-- ----------------------------
DROP FUNCTION IF EXISTS `mycat_seq_nextval`;
DELIMITER ;;
CREATE FUNCTION `mycat_seq_nextval`(seq_name VARCHAR(64)) RETURNS varchar(64) CHARSET latin1
    DETERMINISTIC
BEGIN
    DECLARE retval VARCHAR(64);
    DECLARE val BIGINT;
    DECLARE inc INT;
    DECLARE seq_lock INT;
    set val = -1;
    set inc = 0;
    SET seq_lock = -1;
    SELECT GET_LOCK(seq_name, 15) into seq_lock;
    if seq_lock = 1 then
      SELECT current_value + increment, increment INTO val, inc FROM MYCAT_SEQUENCE WHERE name = seq_name for update;
      if val != -1 then
          UPDATE MYCAT_SEQUENCE SET current_value = val WHERE name = seq_name;
      end if;
      SELECT RELEASE_LOCK(seq_name) into seq_lock;
    end if;
    SELECT concat(CAST((val - inc + 1) as CHAR),",",CAST(inc as CHAR)) INTO retval;
    RETURN retval;
END
;;
DELIMITER ;

-- ----------------------------
-- Function structure for `mycat_seq_setvals`
-- ----------------------------
DROP FUNCTION IF EXISTS `mycat_seq_nextvals`;
DELIMITER ;;
CREATE FUNCTION `mycat_seq_nextvals`(seq_name VARCHAR(64), count INT) RETURNS VARCHAR(64) CHARSET latin1
    DETERMINISTIC
BEGIN
    DECLARE retval VARCHAR(64);
    DECLARE val BIGINT;
    DECLARE seq_lock INT;
    SET val = -1;
    SET seq_lock = -1;
    SELECT GET_LOCK(seq_name, 15) into seq_lock;
    if seq_lock = 1 then
        SELECT current_value + count INTO val FROM MYCAT_SEQUENCE WHERE name = seq_name for update;
        IF val != -1 THEN
            UPDATE MYCAT_SEQUENCE SET current_value = val WHERE name = seq_name;
        END IF;
        SELECT RELEASE_LOCK(seq_name) into seq_lock;
    end if;
    SELECT CONCAT(CAST((val - count + 1) as CHAR), ",", CAST(val as CHAR)) INTO retval;
    RETURN retval;
END
;;
DELIMITER ;

-- ----------------------------
-- Function structure for `mycat_seq_setval`
-- ----------------------------
DROP FUNCTION IF EXISTS `mycat_seq_setval`;
DELIMITER ;;
CREATE FUNCTION `mycat_seq_setval`(seq_name VARCHAR(64), value BIGINT) RETURNS varchar(64) CHARSET latin1
    DETERMINISTIC
BEGIN
    DECLARE retval VARCHAR(64);
    DECLARE inc INT;
    SET inc = 0;
    SELECT increment INTO inc FROM MYCAT_SEQUENCE WHERE name = seq_name;
    UPDATE MYCAT_SEQUENCE SET current_value = value WHERE name = seq_name;
    SELECT concat(CAST(value as CHAR),",",CAST(inc as CHAR)) INTO retval;
    RETURN retval;
END
;;
DELIMITER ;

INSERT INTO MYCAT_SEQUENCE VALUES ('GLOBAL', 1, 1);

然后在schema.xmlsequence_db_conf.properties中配置:

schema.xml:

	<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100" randomDataNode="dn1">
		<!--splitTableNames 启用<table name 属性使用逗号分割配置多个表,即多个表使用这个配置-->
		<table name="cz_dept" primaryKey="id" autoIncrement="true" dataNode="dn1,dn2" rule="hash-string"/>
		<table name="mycat_sequence" primaryKey="name" dataNode="dn1"/>
	</schema>

sequence_db_conf.properties:

#sequence stored in datanode
GLOBAL=dn1
CZ_DEPT=dn1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值