Mycat安装与配置详解

需要提前准备两个数据库以便于测试

由于github限制,所以以后新版本从以下地址下载

去这里下载 http://dl.mycat.io (GitHub的mycat: https://github.com/MyCATApache/Mycat-download)
可以看到最新的稳定版是1.6.7.1
之后的都是测试和开发版,所以我们下载稳定版的1.6.7.1
Mycat安装与配置详解_第1张图片

根据不同这里下载不同的版本(这里没有显示全,补过可以通过把鼠标移上去看左下角显示的链接信息)
因为我要下linux版本的。所以我下载第一个Mycat-server-1.6.7.1-release-20190213150257-lin的
Mycat安装与配置详解_第2张图片
下载后上传到Linux上,我的是centos6.5

解压安装包

tar -xvf Mycat-server-1.6.7.1-release-20190213150257-linux.tar.gz
Mycat安装与配置详解_第3张图片
可以看到解压出来的内容都放到mycat文件夹中了。
删除安装包,进入mycat文件夹

在这里插入图片描述
bin:命令文件
catlet:空的,扩展
conf:配置文件(server.xml,schema.xml,rule.xml等)
lib:依赖的jar包
Mycat安装与配置详解_第4张图片
进入conf文件夹配置文件

在mycat根目录创建logs文件夹,会把日志自动记录到这里。
如果启动报错可以到此目录查看日志
我在安装的时候发现一个错误
本地主机名未知,我的linux主机名称为test1,所以报错,需要在hosts文件中加上我的主机名字
在这里插入图片描述
编辑hosts文件:vim /etc/hosts

在这里插入图片描述
把我的主机名test1加上即可.
在这里插入图片描述

通过命令:ps -ef | grep mycat 查看服务是否已经确认启动成功

确认成功之后开始配置conf文件夹下的schema.xml、server.xml、rule.xml

配置schema.xml

在后面的测试环节有对此配置的说明内容,很详细。



<mycat:schema xmlns:mycat="http://io.mycat/">


	
	<schema name="mydatabase" checkSQLschema="true" sqlMaxLimit="100">
		
		<table name="t_user" dataNode="dn1,dn2,dn3" primaryKey="id" rule="auto-sharding-long">
					
			<childTable name="t_loginlog" primaryKey="id" joinKey="user_id" parentKey="id">childTable>
		table>
		<table name="t_student" dataNode="dn1,dn3" primaryKey="id" rule="student_id" />
		<table name="t_dictionaries" dataNode="dn1,dn2,dn3" type="global" />
		<table name="t_teacher" dataNode="dn1" />
    schema>
		
		
		<dataNode name="dn1" dataHost="dtHost1" database="db1" />
		<dataNode name="dn2" dataHost="dtHost1" database="db2" />
		<dataNode name="dn3" dataHost="dtHost2" database="db3" />
		
	
	<dataHost name="dtHost1" maxCon="1000" minCon="10" balance="1"
			  writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
		
		<heartbeat>select user()heartbeat>
		
		<writeHost host="127.0.0.1" url="192.168.199.11:3306" user="root" password="123456">
			<readHost host="127.0.0.1" url="192.168.199.12:3306" user="root" password="123456" />
		writeHost>
	
	dataHost>
	<dataHost name="dtHost2" maxCon="1000" minCon="10" balance="1"
			  writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
		
		<heartbeat>select user()heartbeat>
		
		<writeHost host="127.0.0.1" url="192.168.199.13:3306" user="root" password="123456">
			<readHost host="127.0.0.1" url="192.168.199.13:3306" user="root" password="123456" />
		writeHost>
	
	dataHost>
mycat:schema>

配置server.xml




<mycat:server xmlns:mycat="http://io.mycat/">
	<system>
	
    <property name="serverPort">8066property>
	<property name="nonePasswordLogin">0property> 
	<property name="useHandshakeV10">1property>
	<property name="useSqlStat">0property>  
	<property name="useGlobleTableCheck">0property>  

		<property name="sequnceHandlerType">2property>
	<property name="subqueryRelationshipCheck">falseproperty> 
       
         
	
	
        
		<property name="processorBufferPoolType">0property>
		
		
		
		
		
		
		
		
		<property name="handleDistributedTransactions">0property>
		
			
		<property name="useOffHeapForMerge">1property>

		
        <property name="memoryPageSize">64kproperty>

		
		<property name="spillsFileBufferSize">1kproperty>

		<property name="useStreamOutput">0property>

		
		<property name="systemReserveMemorySize">384mproperty>


		
		<property name="useZKSwitch">falseproperty>

		
		

		
		
		
		<property name="strictTxIsolation">falseproperty>
		
		<property name="useZKSwitch">trueproperty>
		
	system>
	
	
	
	
	
	
	
	
	
	<firewall>
	   <whitehost>
	      <host host="192.*" user="root"/>
		  <host host="127.*" user="root"/>
	   whitehost>
       <blacklist check="false">
       blacklist>
	firewall>
	
	
	<user name="root" defaultAccount="true">
		<property name="password">123456property>
		<property name="schemas">mydatabaseproperty>
		
		
		
	user>

	

mycat:server>


配置rule.xml




<mycat:rule xmlns:mycat="http://io.mycat/">

	<tableRule name="student_id">
        <rule>
            <columns>idcolumns>
            <algorithm>student_textalgorithm>
        rule>
    tableRule>
	
	
	<tableRule name="rule1">
		<rule>
			<columns>idcolumns>
			<algorithm>func1algorithm>
		rule>
	tableRule>

	<tableRule name="rule2">
		<rule>
			<columns>user_idcolumns>
			<algorithm>func1algorithm>
		rule>
	tableRule>

	<tableRule name="sharding-by-intfile">
		<rule>
			<columns>sharding_idcolumns>
			<algorithm>hash-intalgorithm>
		rule>
	tableRule>
	<tableRule name="auto-sharding-long">
		<rule>
			<columns>idcolumns>
			<algorithm>rang-longalgorithm>
		rule>
	tableRule>
	<tableRule name="mod-long">
		<rule>
			<columns>idcolumns>
			<algorithm>mod-longalgorithm>
		rule>
	tableRule>
	<tableRule name="sharding-by-murmur">
		<rule>
			<columns>idcolumns>
			<algorithm>murmuralgorithm>
		rule>
	tableRule>
	<tableRule name="crc32slot">
		<rule>
			<columns>idcolumns>
			<algorithm>crc32slotalgorithm>
		rule>
	tableRule>
	<tableRule name="sharding-by-month">
		<rule>
			<columns>create_timecolumns>
			<algorithm>partbymonthalgorithm>
		rule>
	tableRule>
	<tableRule name="latest-month-calldate">
		<rule>
			<columns>calldatecolumns>
			<algorithm>latestMonthalgorithm>
		rule>
	tableRule>
	
	<tableRule name="auto-sharding-rang-mod">
		<rule>
			<columns>idcolumns>
			<algorithm>rang-modalgorithm>
		rule>
	tableRule>
	
	<tableRule name="jch">
		<rule>
			<columns>idcolumns>
			<algorithm>jump-consistent-hashalgorithm>
		rule>
	tableRule>





 <function name="student_text"
        class="io.mycat.route.function.AutoPartitionByLong">
        <property name="mapFile">student_text.txtproperty>
    function>
	
	
	
	
	
	
	
	
	<function name="murmur"
		class="io.mycat.route.function.PartitionByMurmurHash">
		<property name="seed">0property>
		<property name="count">2property>
		<property name="virtualBucketTimes">160property>
		
		
	function>

	<function name="crc32slot"
			  class="io.mycat.route.function.PartitionByCRC32PreSlot">
	function>
	<function name="hash-int"
		class="io.mycat.route.function.PartitionByFileMap">
		<property name="mapFile">partition-hash-int.txtproperty>
	function>
	<function name="rang-long"
		class="io.mycat.route.function.AutoPartitionByLong">
		<property name="mapFile">autopartition-long.txtproperty>
	function>
	<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
		
		<property name="count">3property>
	function>

	<function name="func1" class="io.mycat.route.function.PartitionByLong">
		<property name="partitionCount">8property>
		<property name="partitionLength">128property>
	function>
	<function name="latestMonth"
		class="io.mycat.route.function.LatestMonthPartion">
		<property name="splitOneDay">24property>
	function>
	<function name="partbymonth"
		class="io.mycat.route.function.PartitionByMonth">
		<property name="dateFormat">yyyy-MM-ddproperty>
		<property name="sBeginDate">2015-01-01property>
	function>
	
	<function name="rang-mod" class="io.mycat.route.function.PartitionByRangeMod">
        	<property name="mapFile">partition-range-mod.txtproperty>
	function>
	
	<function name="jump-consistent-hash" class="io.mycat.route.function.PartitionByJumpConsistentHash">
		<property name="totalBuckets">3property>
	function>
mycat:rule>

在conf文件夹创建student_text.txt文件

vim student_text.txt
在这里插入图片描述
内容如下,需要注意的是
0-1M ,为0<=id<=10000,
1M-2M,为10000 说明一下:1k=1000 , 1M=10000

0-1M=0
1M-2M=1

schema.xml中t_student的 table标签值对应了两个dataNode节点,所以此处只有两个规则,不能多,也不能少

<table name="t_student" dataNode="dn1,dn3" primaryKey="id" rule="student_id" />

配置完成后就可以启动mycat进行测试了

在bin文件夹下执行./mycat start
然后通过navicat进行连接,注意端口为之前配置的8066,用户名和密码也是之前配置的root/123456,连接地址为mycat安装主机地址
192.168.199.11和192.168.199.12为双机热备的物理库,
192.168.199.13为单机库,
mycat为逻辑库,通过逻辑库做增删改查、建表、删除表等表操作都会同步在其他物理库上执行。
Mycat安装与配置详解_第5张图片

手动在物理库上创建好已经定义的库

然后在mycat中执行sql创建表,并自动同步到物理库中,注意是mycat执行建表sql

DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
  `id` int(11) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;




DROP TABLE IF EXISTS `t_student`;

CREATE TABLE `t_student` (
  `id` int(11) NOT NULL,
  `s_name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;





DROP TABLE IF EXISTS `t_teacher`;
CREATE TABLE `t_teacher` (
  `id` int(11) NOT NULL,
  `t_name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


DROP TABLE IF EXISTS `t_loginlog`;

CREATE TABLE `t_loginlog` (
  `id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  `create_time` date DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;



DROP TABLE IF EXISTS `t_dictionaries`;

CREATE TABLE `t_dictionaries` (
  `id` int(11) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

在mycat中执行插入数据sql

INSERT INTO `t_student` VALUES ('0', '00');
INSERT INTO `t_student` VALUES ('1', '111');
INSERT INTO `t_student` VALUES ('10000', '10000');
INSERT INTO `t_student` VALUES ('10001', '10001');
INSERT INTO `t_student` VALUES ('20000', '20000');

INSERT INTO `t_user` VALUES ('1', '111');
INSERT INTO `t_user` VALUES ('10000001', '10000001');
INSERT INTO `t_user` VALUES ('5000001', '5000001');

INSERT INTO `t_loginlog` VALUES ('1', '1', '2019-03-08');
INSERT INTO `t_loginlog` VALUES ('3', '10000001', '2019-03-06');
INSERT INTO `t_loginlog` VALUES ('2', '5000001', '2019-03-07');

INSERT INTO `t_dictionaries` VALUES ('1', '1');

打开mycat查看刚刚插入的数据,
Mycat安装与配置详解_第6张图片
首先确认t_student的数据,分片节点为dn1和dn3对应db1和db3的物理库,并分别存储在dtHost1和dtHost2两台mysql上
分片规则为
0-1M=0
1M-2M=1
确认物理库确实根据ID分开进行存储
Mycat安装与配置详解_第7张图片

确认t_user是否进行了分片,t_loginlog是否根据和t_user的主外键规则进行分片

Mycat安装与配置详解_第8张图片
确认t_user确实按照ID进行了分片,t_loginlog确实根据t_user的外键关联进行了分片,因为我的SQL并没有写主外键的约束,所以我手动往t_loginlog也是可以插入数据的

t_dictionaries表为全局表,所以他的数据操作是同步在所有的数据节点上,

配置了3个数据节点,所以3个数据节点中的数据是一致的
此处就不截图了。

t_teacher 并没有进行分片配置,也只定义了一个节点所以是单表,确认只有一个物理库中存在即可。

Mycat安装与配置详解_第9张图片

至此已经搭建完毕

rule规则详解



 常用的分片规则:总共十个(基本够用)
 
一、枚举法
<tableRule name="sharding-by-intfile">
    <rule>
      <columns>user_idcolumns>
      <algorithm>hash-intalgorithm>
    rule>
  tableRule>
<function name="hash-int" class="io.mycat.route.function.PartitionByFileMap">
    <property name="mapFile">partition-hash-int.txtproperty>
    <property name="type">0property>
    <property name="defaultNode">0property>
  function>
 
partition-hash-int.txt 配置:
10000=0
10010=1
上面columns 标识将要分片的表字段,algorithm 分片函数,
其中分片函数配置中,mapFile标识配置文件名称,type默认值为0,0表示Integer,非零表示String,
所有的节点配置都是从0开始,及0代表节点1
/**
*  defaultNode 默认节点:小于0表示不设置默认节点,大于等于0表示设置默认节点,结点为指定的值
* 
默认节点的作用:枚举分片时,如果碰到不识别的枚举值,就让它路由到默认节点
*                如果不配置默认节点(defaultNode值小于0表示不配置默认节点),碰到
*                不识别的枚举值就会报错,
*                like this:can't find datanode for sharding column:column_name val:ffffffff    
*/
 
二、固定分片hash算法
<tableRule name="rule1">
    <rule>
      <columns>user_idcolumns>
      <algorithm>func1algorithm>
    rule>
tableRule>
 
  <function name="func1" class="io.mycat.route.function.PartitionByLong">
    <property name="partitionCount">2,1property>
    <property name="partitionLength">256,512property>
  function>
配置说明:
上面columns 标识将要分片的表字段,algorithm 分片函数,
partitionCount 分片个数列表,partitionLength 分片范围列表
分区长度:默认为最大2^n=1024 ,即最大支持1024分区
约束 :
count,length两个数组的长度必须是一致的。
1024 = sum((count[i]*length[i])). count和length两个向量的点积恒等于1024
用法例子:
@Test
public void testPartition() {
// 本例的分区策略:希望将数据水平分成3份,前两份各占25%,第三份占50%。(故本例非均匀分区)
// |<---------------------1024------------------------>|
// |<----256--->|<----256--->|<----------512---------->|
// | partition0 | partition1 | partition2 |
// | 共2份,故count[0]=2 | 共1份,故count[1]=1 |
int[] count = new int[] { 2, 1 };
int[] length = new int[] { 256, 512 };
PartitionUtil pu = new PartitionUtil(count, length);

// 下面代码演示分别以offerId字段或memberId字段根据上述分区策略拆分的分配结果
int DEFAULT_STR_HEAD_LEN = 8; // cobar默认会配置为此值
long offerId = 12345;
String memberId = "qiushuo";

// 若根据offerId分配,partNo1将等于0,即按照上述分区策略,offerId为12345时将会被分配到partition0中
int partNo1 = pu.partition(offerId);

// 若根据memberId分配,partNo2将等于2,即按照上述分区策略,memberId为qiushuo时将会被分到partition2中
int partNo2 = pu.partition(memberId, 0, DEFAULT_STR_HEAD_LEN);

Assert.assertEquals(0, partNo1);
Assert.assertEquals(2, partNo2);
}
 
如果需要平均分配设置:平均分为4分片,partitionCount*partitionLength=1024
<function name="func1" class="org.opencloudb.route.function.PartitionByLong">
    <property name="partitionCount">4property>
    <property name="partitionLength">256property>
  function>
 
三、范围约定
<tableRule name="auto-sharding-long">
    <rule>
      <columns>user_idcolumns>
      <algorithm>rang-longalgorithm>
    rule>
  tableRule>
<function name="rang-long" class="io.mycat.route.function.AutoPartitionByLong">
    <property name="mapFile">autopartition-long.txtproperty>
  function>
# range start-end ,data node index
# K=1000,M=10000.
0-500M=0
500M-1000M=1
1000M-1500M=2
或
0-10000000=0
10000001-20000000=1
 
 
配置说明:
上面columns 标识将要分片的表字段,algorithm 分片函数,
rang-long 函数中mapFile代表配置文件路径
所有的节点配置都是从0开始,及0代表节点1,此配置非常简单,即预先制定可能的id范围到某个分片
 
四、求模法
<tableRule name="mod-long">
    <rule>
      <columns>user_idcolumns>
      <algorithm>mod-longalgorithm>
    rule>
  tableRule>
  <function name="mod-long" class="io.mycat.route.function.PartitionByMod">
   
    <property name="count">3property>
  function>
 
配置说明:
上面columns 标识将要分片的表字段,algorithm 分片函数,
此种配置非常明确即根据id与count(你的结点数)进行求模预算,相比方式1,此种在批量插入时需要切换数据源,id不连续
 
五、日期列分区法
<tableRule name="sharding-by-date">
      <rule>
        <columns>create_timecolumns>
        <algorithm>sharding-by-datealgorithm>
      rule>
   tableRule> 
<function name="sharding-by-date" class="io.mycat.route.function..PartitionByDate">
   <property name="dateFormat">yyyy-MM-ddproperty>
    <property name="sBeginDate">2014-01-01property>
    <property name="sPartionDay">10property>
  function>
配置说明:
上面columns 标识将要分片的表字段,algorithm 分片函数,
配置中配置了开始日期,分区天数,即默认从开始日期算起,分隔10天一个分区
 
还有一切特性请看源码
 
 
Assert.assertEquals(true, 0 == partition.calculate("2014-01-01"));
Assert.assertEquals(true, 0 == partition.calculate("2014-01-10"));
Assert.assertEquals(true, 1 == partition.calculate("2014-01-11"));
Assert.assertEquals(true, 12 == partition.calculate("2014-05-01"));
 
 
 
六、通配取模
<tableRule name="sharding-by-pattern">
      <rule>
        <columns>user_idcolumns>
        <algorithm>sharding-by-patternalgorithm>
      rule>
   tableRule>
<function name="sharding-by-pattern" class="io.mycat.route.function.PartitionByPattern">
    <property name="patternValue">256property>
    <property name="defaultNode">2property>
    <property name="mapFile">partition-pattern.txtproperty>
 
  function>
partition-pattern.txt 
# id partition range start-end ,data node index
###### first host configuration
1-32=0
33-64=1
65-96=2
97-128=3
######## second host configuration
129-160=4
161-192=5
193-224=6
225-256=7
0-0=7
配置说明:
上面columns 标识将要分片的表字段,algorithm 分片函数,patternValue 即求模基数,defaoultNode 默认节点,如果不配置了默认,则默认是0即第一个结点
mapFile 配置文件路径
配置文件中,1-32 即代表id%256后分布的范围,如果在1-32则在分区1,其他类推,如果id非数字数据,则会分配在defaoultNode 默认节点
 
 
String idVal = "0";
Assert.assertEquals(true, 7 == autoPartition.calculate(idVal));
idVal = "45a";
Assert.assertEquals(true, 2 == autoPartition.calculate(idVal));
 
七、ASCII码求模通配
<tableRule name="sharding-by-prefixpattern">
      <rule>
        <columns>user_idcolumns>
        <algorithm>sharding-by-prefixpatternalgorithm>
      rule>
   tableRule>
<function name="sharding-by-pattern" class="io.mycat.route.function.PartitionByPrefixPattern">
    <property name="patternValue">256property>
    <property name="prefixLength">5property>
    <property name="mapFile">partition-pattern.txtproperty>
 
  function>
 
partition-pattern.txt
 
# range start-end ,data node index
# ASCII
# 48-57=0-9
# 64、65-90=@、A-Z
# 97-122=a-z
###### first host configuration
1-4=0
5-8=1
9-12=2
13-16=3
###### second host configuration
17-20=4
21-24=5
25-28=6
29-32=7
0-0=7
配置说明:
上面columns 标识将要分片的表字段,algorithm 分片函数,patternValue 即求模基数,prefixLength ASCII 截取的位数
mapFile 配置文件路径
配置文件中,1-32 即代表id%256后分布的范围,如果在1-32则在分区1,其他类推 
 
此种方式类似方式6只不过采取的是将列种获取前prefixLength位列所有ASCII码的和进行求模sum%patternValue ,获取的值,在通配范围内的
即 分片数,
/**
* ASCII编码:
* 48-57=0-9阿拉伯数字
* 64、65-90=@、A-Z
* 97-122=a-z
*
*/
如 
 
String idVal="gf89f9a";
Assert.assertEquals(true, 0==autoPartition.calculate(idVal));

idVal="8df99a";
Assert.assertEquals(true, 4==autoPartition.calculate(idVal));

idVal="8dhdf99a";
Assert.assertEquals(true, 3==autoPartition.calculate(idVal));
 
八、编程指定
<tableRule name="sharding-by-substring">
      <rule>
        <columns>user_idcolumns>
        <algorithm>sharding-by-substringalgorithm>
      rule>
   tableRule>
<function name="sharding-by-substring" class="io.mycat.route.function.PartitionDirectBySubString">
    <property name="startIndex">0property> 
    <property name="size">2property>
    <property name="partitionCount">8property>
    <property name="defaultPartition">0property>
  function>
配置说明:
上面columns 标识将要分片的表字段,algorithm 分片函数 
此方法为直接根据字符子串(必须是数字)计算分区号(由应用传递参数,显式指定分区号)。
例如id=05-100000002
在此配置中代表根据id中从startIndex=0,开始,截取siz=2位数字即05,05就是获取的分区,如果没传默认分配到defaultPartition
 
九、字符串拆分hash解析
<tableRule name="sharding-by-stringhash">
      <rule>
        <columns>user_idcolumns>
        <algorithm>sharding-by-stringhashalgorithm>
      rule>
   tableRule>
<function name="sharding-by-substring" class="io.mycat.route.function.PartitionByString">
    <property name=length>512property> 
    <property name="count">2property>
    <property name="hashSlice">0:2property>
  function>
配置说明:
上面columns 标识将要分片的表字段,algorithm 分片函数 
函数中length代表字符串hash求模基数,count分区数,hashSlice hash预算位
即根据子字符串 hash运算
 
hashSlice : 0 means str.length(), -1 means str.length()-1
 
/**
     * "2" -> (0,2)<br/>
     * "1:2" -> (1,2)<br/>
     * "1:" -> (1,0)<br/>
     * "-1:" -> (-1,0)<br/>
     * ":-1" -> (0,-1)<br/>
     * ":" -> (0,0)<br/>
     */
public class PartitionByStringTest {

@Test
public void test() {
PartitionByString rule = new PartitionByString();
String idVal=null;
rule.setPartitionLength("512");
rule.setPartitionCount("2");
rule.init();
rule.setHashSlice("0:2");
//    idVal = "0";
//    Assert.assertEquals(true, 0 == rule.calculate(idVal));
//    idVal = "45a";
//    Assert.assertEquals(true, 1 == rule.calculate(idVal));



//last 4
rule = new PartitionByString();
rule.setPartitionLength("512");
rule.setPartitionCount("2");
rule.init();
//last 4 characters
rule.setHashSlice("-4:0");
idVal = "aaaabbb0000";
Assert.assertEquals(true, 0 == rule.calculate(idVal));
idVal = "aaaabbb2359";
Assert.assertEquals(true, 0 == rule.calculate(idVal));
}
 
十、一致性hash
<tableRule name="sharding-by-murmur">
      <rule>
        <columns>user_idcolumns>
        <algorithm>murmuralgorithm>
      rule>
   tableRule>
<function name="murmur" class="io.mycat.route.function.PartitionByMurmurHash">
      <property name="seed">0property>
      <property name="count">2property>
      
      
  function>



你可能感兴趣的:(MySQl)