进学阁

业精于勤荒于嬉,行成于思毁于随

0%

分布式架构上

1、分布式架构-演变

2、基础架构介绍

2.1 环境准备:

  • 两台虚拟机 db01 db02
  • 每台创建四个mysql实例:3307 3308 / 3309 3310

2.2 删除历史环境:

1
2
3
pkill mysqld
rm -rf /data/330*
mv /etc/my.cnf /etc/my.cnf.bak

2.3 创建相关目录初始化数据

1
2
3
4
5
6
7
8
9
mkdir /data/33{07..10}/data -p
mysqld --initialize-insecure --user=mysql --datadir=/data/3307/data --
basedir=/data/app/mysql
mysqld --initialize-insecure --user=mysql --datadir=/data/3308/data --
basedir=/data/app/mysql
mysqld --initialize-insecure --user=mysql --datadir=/data/3309/data --
basedir=/data/app/mysql
mysqld --initialize-insecure --user=mysql --datadir=/data/3310/data --
basedir=/data/app/mysql

2.4 准备配置文件和启动脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
# ========db01==============
cat >/data/3307/my.cnf<<EOF
[mysqld]
basedir=/data/app/mysql
datadir=/data/3307/data
socket=/data/3307/mysql.sock
port=3307
log-error=/data/3307/mysql.log
log_bin=/data/3307/mysql-bin
binlog_format=row
skip-name-resolve
server-id=7
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
#*************** rpl_semi_sync ***************
rpl_semi_sync_master_enabled =ON
rpl_semi_sync_master_timeout =5000
rpl_semi_sync_master_wait_for_slave_count =1
rpl_semi_sync_master_wait_no_slave =ON
rpl_semi_sync_master_wait_point =AFTER_SYNC
rpl_semi_sync_slave_enabled =ON
#*************** group commit ***************
binlog_group_commit_sync_delay =1
binlog_group_commit_sync_no_delay_count =1000
#*************** gtid ***************
gtid_mode =ON
enforce_gtid_consistency =ON
log_slave_update =1
#*************** gtid ***************
slave_parallel_type =LOGICAL_CLOCK
slave_parallel_workers =4
master_info_repository =TABLE
relay_log_info_repository =TABLE
EOF

cat >/data/3308/my.cnf<<EOF
[mysqld]
basedir=/data/app/mysql
datadir=/data/3308/data
port=3308
socket=/data/3308/mysql.sock
log-error=/data/3308/mysql.log
log_bin=/data/3308/mysql-bin
binlog_format=row
skip-name-resolve
server-id=8
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
#*************** rpl_semi_sync ***************
rpl_semi_sync_master_enabled =ON
rpl_semi_sync_master_timeout =5000
rpl_semi_sync_master_wait_for_slave_count =1
rpl_semi_sync_master_wait_no_slave =ON
rpl_semi_sync_master_wait_point =AFTER_SYNC
rpl_semi_sync_slave_enabled =ON
#*************** group commit ***************
binlog_group_commit_sync_delay =1
binlog_group_commit_sync_no_delay_count =1000
#*************** gtid ***************
gtid_mode =ON
enforce_gtid_consistency =ON
log_slave_update =1
#*************** gtid ***************
slave_parallel_type =LOGICAL_CLOCK
slave_parallel_workers =4
master_info_repository =TABLE
relay_log_info_repository =TABLE
EOF

cat >/data/3309/my.cnf<<EOF
[mysqld]
basedir=/data/app/mysql
datadir=/data/3309/data
socket=/data/3309/mysql.sock
port=3309
log-error=/data/3309/mysql.log
log_bin=/data/3309/mysql-bin
binlog_format=row
skip-name-resolve
server-id=9
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
#*************** rpl_semi_sync ***************
rpl_semi_sync_master_enabled =ON
rpl_semi_sync_master_timeout =5000
rpl_semi_sync_master_wait_for_slave_count =1
rpl_semi_sync_master_wait_no_slave =ON
rpl_semi_sync_master_wait_point =AFTER_SYNC
rpl_semi_sync_slave_enabled =ON
#*************** group commit ***************
binlog_group_commit_sync_delay =1
binlog_group_commit_sync_no_delay_count =1000
#*************** gtid ***************
gtid_mode =ON
enforce_gtid_consistency =ON
log_slave_update =1
#*************** gtid ***************
slave_parallel_type =LOGICAL_CLOCK
slave_parallel_workers =4
master_info_repository =TABLE
relay_log_info_repository =TABLE
EOF

cat >/data/3310/my.cnf<<EOF
[mysqld]
basedir=/data/app/mysql
datadir=/data/3310/data
socket=/data/3310/mysql.sock
port=3310
log-error=/data/3310/mysql.log
log_bin=/data/3310/mysql-bin
binlog_format=row
skip-name-resolve
server-id=10
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
#*************** rpl_semi_sync ***************
rpl_semi_sync_master_enabled =ON
rpl_semi_sync_master_timeout =5000
rpl_semi_sync_master_wait_for_slave_count =1
rpl_semi_sync_master_wait_no_slave =ON
rpl_semi_sync_master_wait_point =AFTER_SYNC
rpl_semi_sync_slave_enabled =ON
#*************** group commit ***************
binlog_group_commit_sync_delay =1
binlog_group_commit_sync_no_delay_count =1000
#*************** gtid ***************
gtid_mode =ON
enforce_gtid_consistency =ON
log_slave_update =1
#*************** gtid ***************
slave_parallel_type =LOGICAL_CLOCK
slave_parallel_workers =4
master_info_repository =TABLE
relay_log_info_repository =TABLE
EOF

cat >/etc/systemd/system/mysqld3307.service<<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
ExecStart=/data/app/mysql/bin/mysqld --defaults-file=/data/3307/my.cnf
LimitNOFILE = 5000
EOF

cat >/etc/systemd/system/mysqld3308.service<<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
ExecStart=/data/app/mysql/bin/mysqld --defaults-file=/data/3308/my.cnf
LimitNOFILE = 5000
EOF

cat >/etc/systemd/system/mysqld3309.service<<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
ExecStart=/data/app/mysql/bin/mysqld --defaults-file=/data/3309/my.cnf
LimitNOFILE = 5000
EOF

cat >/etc/systemd/system/mysqld3310.service<<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
ExecStart=/data/app/mysql/bin/mysqld --defaults-file=/data/3310/my.cnf
LimitNOFILE = 5000
EOF



# ========db02===============
cat >/data/3307/my.cnf<<EOF
[mysqld]
basedir=/data/app/mysql
datadir=/data/3307/data
socket=/data/3307/mysql.sock
port=3307
log-error=/data/3307/mysql.log
log_bin=/data/3307/mysql-bin
binlog_format=row
skip-name-resolve
server-id=17
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
#*************** rpl_semi_sync ***************
rpl_semi_sync_master_enabled =ON
rpl_semi_sync_master_timeout =5000
rpl_semi_sync_master_wait_for_slave_count =1
rpl_semi_sync_master_wait_no_slave =ON
rpl_semi_sync_master_wait_point =AFTER_SYNC
rpl_semi_sync_slave_enabled =ON
#*************** group commit ***************
binlog_group_commit_sync_delay =1
binlog_group_commit_sync_no_delay_count =1000
#*************** gtid ***************
gtid_mode =ON
enforce_gtid_consistency =ON
log_slave_update =1
#*************** gtid ***************
slave_parallel_type =LOGICAL_CLOCK
slave_parallel_workers =4
master_info_repository =TABLE
relay_log_info_repository =TABLE
EOF

cat >/data/3308/my.cnf<<EOF
[mysqld]
basedir=/data/app/mysql
datadir=/data/3308/data
port=3308
socket=/data/3308/mysql.sock
log-error=/data/3308/mysql.log
log_bin=/data/3308/mysql-bin
binlog_format=row
skip-name-resolve
server-id=18
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
#*************** rpl_semi_sync ***************
rpl_semi_sync_master_enabled =ON
rpl_semi_sync_master_timeout =5000
rpl_semi_sync_master_wait_for_slave_count =1
rpl_semi_sync_master_wait_no_slave =ON
rpl_semi_sync_master_wait_point =AFTER_SYNC
rpl_semi_sync_slave_enabled =ON
#*************** group commit ***************
binlog_group_commit_sync_delay =1
binlog_group_commit_sync_no_delay_count =1000
#*************** gtid ***************
gtid_mode =ON
enforce_gtid_consistency =ON
log_slave_update =1
#*************** gtid ***************
slave_parallel_type =LOGICAL_CLOCK
slave_parallel_workers =4
master_info_repository =TABLE
relay_log_info_repository =TABLE
EOF

cat >/data/3309/my.cnf<<EOF
[mysqld]
basedir=/data/app/mysql
datadir=/data/3309/data
socket=/data/3309/mysql.sock
port=3309
log-error=/data/3309/mysql.log
log_bin=/data/3309/mysql-bin
binlog_format=row
skip-name-resolve
server-id=19
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
#*************** rpl_semi_sync ***************
rpl_semi_sync_master_enabled =ON
rpl_semi_sync_master_timeout =5000
rpl_semi_sync_master_wait_for_slave_count =1
rpl_semi_sync_master_wait_no_slave =ON
rpl_semi_sync_master_wait_point =AFTER_SYNC
rpl_semi_sync_slave_enabled =ON
#*************** group commit ***************
binlog_group_commit_sync_delay =1
binlog_group_commit_sync_no_delay_count =1000
#*************** gtid ***************
gtid_mode =ON
enforce_gtid_consistency =ON
log_slave_update =1
#*************** gtid ***************
slave_parallel_type =LOGICAL_CLOCK
slave_parallel_workers =4
master_info_repository =TABLE
relay_log_info_repository =TABLE
EOF

cat >/data/3310/my.cnf<<EOF
[mysqld]
basedir=/data/app/mysql
datadir=/data/3310/data
socket=/data/3310/mysql.sock
port=3310
log-error=/data/3310/mysql.log
log_bin=/data/3310/mysql-bin
binlog_format=row
skip-name-resolve
server-id=20
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
#*************** rpl_semi_sync ***************
rpl_semi_sync_master_enabled =ON
rpl_semi_sync_master_timeout =5000
rpl_semi_sync_master_wait_for_slave_count =1
rpl_semi_sync_master_wait_no_slave =ON
rpl_semi_sync_master_wait_point =AFTER_SYNC
rpl_semi_sync_slave_enabled =ON
#*************** group commit ***************
binlog_group_commit_sync_delay =1
binlog_group_commit_sync_no_delay_count =1000
#*************** gtid ***************
gtid_mode =ON
enforce_gtid_consistency =ON
log_slave_update =1
#*************** gtid ***************
slave_parallel_type =LOGICAL_CLOCK
slave_parallel_workers =4
master_info_repository =TABLE
relay_log_info_repository =TABLE
EOF

cat >/etc/systemd/system/mysqld3307.service<<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
ExecStart=/data/app/mysql/bin/mysqld --defaults-file=/data/3307/my.cnf
LimitNOFILE = 5000
EOF

cat >/etc/systemd/system/mysqld3308.service<<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
ExecStart=/data/app/mysql/bin/mysqld --defaults-file=/data/3308/my.cnf
LimitNOFILE = 5000
EOF

cat >/etc/systemd/system/mysqld3309.service<<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
ExecStart=/data/app/mysql/bin/mysqld --defaults-file=/data/3309/my.cnf
LimitNOFILE = 5000
EOF

cat >/etc/systemd/system/mysqld3310.service<<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
ExecStart=/data/app/mysql/bin/mysqld --defaults-file=/data/3310/my.cnf
LimitNOFILE = 5000
EOF

2.5 修改权限,启动多实例

1
2
3
4
5
6
7
8
9
chown -R mysql.mysql /data/*
systemctl start mysqld3307
systemctl start mysqld3308
systemctl start mysqld3309
systemctl start mysqld3310
mysql -S /data/3307/mysql.sock -e "show variables like 'server_id'"
mysql -S /data/3308/mysql.sock -e "show variables like 'server_id'"
mysql -S /data/3309/mysql.sock -e "show variables like 'server_id'"
mysql -S /data/3310/mysql.sock -e "show variables like 'server_id'"

2.6 节点主从规划

1
2
3
10.0.0.52:3308 <-----> 10.0.0.51:3308
10.0.0.52:3310 -----> 10.0.0.52:3308
10.0.0.51:3310 -----> 10.0.0.51:3308

2.7 开始配置主从环境

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# shard1
## 10.0.0.51:3307 <-----> 10.0.0.52:3307
# db02
mysql -S /data/3307/mysql.sock -e "create user repl@'10.0.0.%' identified
with mysql_native_password by '123'; grant replication slave on *.* to
repl@'10.0.0.%';"
mysql -S /data/3307/mysql.sock -e "create user root@'10.0.0.%' identified
with mysql_native_password by '123'; grant all on *.* to root@'10.0.0.%';
"
# db01
mysql -S /data/3307/mysql.sock -e "CHANGE MASTER TO
MASTER_HOST='10.0.0.52', MASTER_PORT=3307, MASTER_AUTO_POSITION=1,
MASTER_USER='repl', MASTER_PASSWORD='123';"
mysql -S /data/3307/mysql.sock -e "start slave;"
mysql -S /data/3307/mysql.sock -e "show slave status\G"|grep Running:
# db02
mysql -S /data/3307/mysql.sock -e "CHANGE MASTER TO
MASTER_HOST='10.0.0.51', MASTER_PORT=3307, MASTER_AUTO_POSITION=1,
MASTER_USER='repl', MASTER_PASSWORD='123';"
mysql -S /data/3307/mysql.sock -e "start slave;"
mysql -S /data/3307/mysql.sock -e "show slave status\G"|grep Running:
## 10.0.0.51:3309 ------> 10.0.0.51:3307

# db01
mysql -S /data/3309/mysql.sock -e "CHANGE MASTER TO
MASTER_HOST='10.0.0.51', MASTER_PORT=3307, MASTER_AUTO_POSITION=1,
MASTER_USER='repl', MASTER_PASSWORD='123';"
mysql -S /data/3309/mysql.sock -e "start slave;"
mysql -S /data/3309/mysql.sock -e "show slave status\G"|grep Running:
## 10.0.0.52:3309 ------> 10.0.0.52:3307
# db02
mysql -S /data/3309/mysql.sock -e "CHANGE MASTER TO
MASTER_HOST='10.0.0.52', MASTER_PORT=3307, MASTER_AUTO_POSITION=1,
MASTER_USER='repl', MASTER_PASSWORD='123';"
mysql -S /data/3309/mysql.sock -e "start slave;"
mysql -S /data/3309/mysql.sock -e "show slave status\G"|grep Running:


====================================================================
# shard2
## 10.0.0.52:3308 <-----> 10.0.0.51:3308
# db01
mysql -S /data/3308/mysql.sock -e "create user repl@'10.0.0.%' identified
with mysql_native_password by '123'; grant replication slave on *.* to
repl@'10.0.0.%';"
mysql -S /data/3308/mysql.sock -e "create user root@'10.0.0.%' identified
with mysql_native_password by '123'; grant all on *.* to root@'10.0.0.%';
"
# db02
mysql -S /data/3308/mysql.sock -e "CHANGE MASTER TO
MASTER_HOST='10.0.0.51', MASTER_PORT=3308, MASTER_AUTO_POSITION=1,
MASTER_USER='repl', MASTER_PASSWORD='123';"
mysql -S /data/3308/mysql.sock -e "start slave;"
mysql -S /data/3308/mysql.sock -e "show slave status\G"|grep Running:
# db01
mysql -S /data/3308/mysql.sock -e "CHANGE MASTER TO
MASTER_HOST='10.0.0.52', MASTER_PORT=3308, MASTER_AUTO_POSITION=1,
MASTER_USER='repl', MASTER_PASSWORD='123';"
mysql -S /data/3308/mysql.sock -e "start slave;"
mysql -S /data/3308/mysql.sock -e "show slave status\G"|grep Running:
## 10.0.0.52:3310 -----> 10.0.0.52:3308
# db02
mysql -S /data/3310/mysql.sock -e "CHANGE MASTER TO
MASTER_HOST='10.0.0.52', MASTER_PORT=3308, MASTER_AUTO_POSITION=1,
MASTER_USER='repl', MASTER_PASSWORD='123';"
mysql -S /data/3310/mysql.sock -e "start slave;"
mysql -S /data/3310/mysql.sock -e "show slave status\G"|grep Running:
##10.0.0.51:3310 -----> 10.0.0.51:3308

# db01
mysql -S /data/3310/mysql.sock -e "CHANGE MASTER TO
MASTER_HOST='10.0.0.51', MASTER_PORT=3308, MASTER_AUTO_POSITION=1,
MASTER_USER='repl', MASTER_PASSWORD='123';"
mysql -S /data/3310/mysql.sock -e "start slave;"
mysql -S /data/3310/mysql.sock -e "show slave status\G"|grep Running:
2.9 检测主从状态
mysql -S /data/3307/mysql.sock -e "show slave status\G"|grep Yes
mysql -S /data/3308/mysql.sock -e "show slave status\G"|grep Yes
mysql -S /data/3309/mysql.sock -e "show slave status\G"|grep Yes
mysql -S /data/3310/mysql.sock -e "show slave status\G"|grep Yes
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
注:如果中间出现错误,在每个节点进行执行以下命令,从2.8从头执行
mysql -S /data/3307/mysql.sock -e "stop slave; reset slave all;"
mysql -S /data/3308/mysql.sock -e "stop slave; reset slave all;"
mysql -S /data/3309/mysql.sock -e "stop slave; reset slave all;"
mysql -S /data/3310/mysql.sock -e "stop slave; reset slave all;"

3.MyCAT安装

3.1 预先安装Java运行环境

yum install -y java

3.2下载

1
2
Mycat-server-xxxxx.linux.tar.gz
http://dl.mycat.org.cn/

3.3 解压文件

tar xf Mycat-server-*

3.4 软件目录结构

1
2
ls
bin catlet conf lib logs version.txt

3.5 启动和连接

1
2
3
4
5
6
7
8
9
10
11
12
13
vim /etc/profile
export PATH=/data/app/mycat/bin:$PATH
source /etc/profile
mycat start
mysql -uroot -p123456 -h 127.0.0.1 -P8066
注: Mycat中使用的是MySQL 5.1版本驱动,连接8.0时将会失败。

# 解决方案:
1. 下载更新客户端程序
https://downloads.mysql.com/archives/c-j/
2. 连接时添加auth=mysql_native_password参数
mysql -uroot -p123456 -h10.0.0.51 -P8066 --defaultauth=mysql_native_password
3. 更新MySQL客户端命令为8.0之前版本

4.配置文件介绍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
4.1 bin 目录
程序目录
4.2 conf
配置文件目录
4.2.1 schema.xml
主配置文件:节点信息、读写分离、高可用设置、调用分片策略..
4.2.2 rule.xml
分片策略的定义、功能、使用用方法
4.2.3 server.xml
mycat服务有关配置: 用户、网络、权限、策略、资源...
4.2.4 xx.txt文件
分片参数定义文件
4.2.5 log4j2.xml
Mycat 相关日志记录配置
4.3 logs
wrapper.log : 启动日志
mycat.log :工作日志

5.schema.xml配置文件基本结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@db01 conf]# cd /data/mycat/conf/
mv schema.xml schema.xml.bak
vim schema.xml
# 逻辑库:
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100"
dataNode="dn1">
</schema>
# DN数据节点(逻辑分片):数据节点(逻辑分片):
<dataNode name="dn1" dataHost="localhost1" database= "world" />
作用:
垂直和水平查分。
# DH 数据主机
作用: 高可用和读写分离
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="1">
<heartbeat>select user()</heartbeat>
<writeHost host="db1" url="10.0.0.51:3307" user="root" password="123">
<readHost host="db2" url="10.0.0.51:3309" user="root"
password="123" />
</writeHost>
</dataHost>
</mycat:schema>
====================================
<?xml version="1.0"?>

5.2 配置文件简单试水-读写分离

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#配置文件模板-读写分离
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100"
dataNode="dn1">
</schema>
<dataNode name="dn1" dataHost="localhost1" database= "world" />
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="1">
<heartbeat>select user()</heartbeat>
<writeHost host="db1" url="10.0.0.51:3307" user="root" password="123">
<readHost host="db2" url="10.0.0.51:3309" user="root"
password="123" />
</writeHost>
</dataHost>
</mycat:schema>
# 测试环境准备
db01:
mysql -S /data/3307/mysql.sock -e "grant all on *.* to root@'10.0.0.%'
identified by '123';"
mysql -S /data/3307/mysql.sock -e "source /root/world.sql"
mysql -S /data/3308/mysql.sock -e "grant all on *.* to root@'10.0.0.%'
identified by '123';"
mysql -S /data/3308/mysql.sock -e "source /root/world.sql"
# 重启mycat
mycat restart
读写分离测试
# 连接mycat 服务
[root@db01 ~]# mysql -uroot -p123456 -h 10.0.0.51 -P8066
# 测试读
mysql> select @@server_id;
# 测试写
mysql> begin ; select @@server_id;commit;

5.3 配置读写分离及高可用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
[root@db01 conf]# mv schema.xml schema.xml.rw
[root@db01 conf]# vim schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100"
dataNode="sh1">
</schema>
<dataNode name="sh1" dataHost="oldguo1" database= "world" />
<dataHost name="oldguo1" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="1">
<heartbeat>select user()</heartbeat>
<writeHost host="db1" url="10.0.0.51:3307" user="root" password="123">
<readHost host="db2" url="10.0.0.51:3309" user="root"
password="123" />
</writeHost>
<writeHost host="db3" url="10.0.0.52:3307" user="root" password="123">
<readHost host="db4" url="10.0.0.52:3309" user="root"
password="123" />
</writeHost>
</dataHost>
</mycat:schema>
primary writehost :负责写操作的writehost
standby writeHost :和readhost一样,只提供读服务
当写节点宕机后,后面跟的readhost也不提供服务,这时候standby的writehost就提供写服务,
后面跟的readhost提供读服务
测试读写分离:
mycat restart
mysql -uroot -p123456 -h 10.0.0.51 -P 8066
mysql> select @@server_id;
mysql> begin;select @@server_id;commit;
测试高可用:
[root@db01 conf]# systemctl stop mysqld3307
mysql -uroot -p123456 -h 10.0.0.51 -P 8066
mysql> select @@server_id;
mysql> begin;select @@server_id;commit;
[root@db01 conf]# systemctl start mysqld3307
mysql -uroot -p123456 -h 10.0.0.51 -P 8066
mysql> select @@server_id;
mysql> begin;select @@server_id;commit;

# 说明:
1. MHA + Mycat+ 3分片
<dataHost name="mha1" maxCon="1000" minCon="10" balance="1" writeType="0"
dbType="mysql" dbDriver="native" switchType="2">
<heartbeat>show slave status</heartbeat>
<writeHost host="db1" url="10.0.0.55:3306" user="root" password="123">
<readHost host="db2" url="10.0.0.52:3306" user="root"
password="123" />
<readHost host="db3" url="10.0.0.53:3306" user="root"
password="123" />
</writeHost>
</dataHost>
<dataHost name="mha2" maxCon="1000" minCon="10" balance="1" writeType="0"
dbType="mysql" dbDriver="native" switchType="2">
<heartbeat>show slave status</heartbeat>
<writeHost host="db1" url="10.0.0.56:3307" user="root" password="123">
<readHost host="db2" url="10.0.0.51:3307" user="root" password="123"
/>
<readHost host="db2" url="10.0.0.53:3307" user="root" password="123"
/>
</writeHost>
</dataHost>
<dataHost name="mha3" maxCon="1000" minCon="10" balance="1" writeType="0"
dbType="mysql" dbDriver="native" switchType="2">
<heartbeat>show slave status</heartbeat>
<writeHost host="db1" url="10.0.0.57:3308" user="root" password="123">
<readHost host="db2" url="10.0.0.51:3308" user="root" password="123"
/>
<readHost host="db2" url="10.0.0.52:3308" user="root" password="123"
/>
</writeHost>
</dataHost>

2. PXC+Mycat+3分片
<dataHost name="pxc1" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="3">
<heartbeat>show status like 'wsrep%'</heartbeat>
<writeHost host="db1" url="10.0.0.51:3306" user="root" password="123">
</writeHost>
<writeHost host="db2" url="10.0.0.52:3306" user="root"
password="123">
</writeHost>
<writeHost host="db3" url="10.0.0.53:3306" user="root"
password="123">
</writeHost>
</dataHost>
...此处省略...

4. 调研: MGR+Mycat+3分片

6. 调研: DBLE

5.4 Schema.xml核心参数介绍

5.4.1 balance属性

1
2
3
4
5
6
7
读操作负载均衡类型,目前的取值有3种:
1. balance="0", 不开启读写分离机制,所有读操作都发送到当前可用的writeHost上。
2. balance="1",全部的readHost与standby writeHost参与select语句的负载均衡,简单的
说,
当双主双从模式(M1->S1,M2->S2,并且M1与 M2互为主备),正常情况下,M2,S1,S2都参与select
语句的负载均衡。
3. balance="2",所有读操作都随机的在writeHost、readhost上分发。

5.4.2 writeType属性

1
2
3
4
5
写操作负载均衡,目前的取值有2种:
1. writeType="0", 所有写操作发送到配置的第一个writeHost,
第一个挂了切到还生存的第二个writeHost,重新启动后已切换后的为主,切换记录在配置文件
中:dnindex.properties .
2. writeType=“1”,所有写操作都随机的发送到配置的writeHost,但不推荐使用

5.4.3 switchType属性

1
2
3
4
5
-1: 表示不自动切换
1 : 默认值,自动切换
2 : 基于MySQL主从同步的状态决定是否切换 ,心跳语句为 show slave status (注意超时参数,
参考orch)
3 : 基于Galary Cluster(PXC,MGC) 切换机制,心跳语句为:show status like 'wsrep%'

5.4.4 连接有关

1
2
maxCon="1000":最大的并发连接数
minCon="10" :mycat在启动之后,会在后端节点上自动开启的连接线程

5.4.5 tempReadHostAvailable=”1”

1
2
3
这个一主一从时(1个writehost,1个readhost时),可以开启这个参数,如果2个writehost,2个
readhost时
<heartbeat>select user()</heartbeat> 监测心跳

5.4.6 checkSQLschema=”false”

1
2
3
4
5
是否检查,在select时的库名字。
例如,执行 select * from TESTDB.t1;
参数开启为true,会自动架构TESTDB去掉。否则会使得后端节点执行报错。
当然如果,TESTDB写成了一个不存在的逻辑库名字,也会报错。
结论: 一般我们可以先use,后select的方式进行查询数据即可避免此类问题。

6.Mycat 分布式架构–垂直分表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
taobao user (sh1),order_t(sh2) ,others(sh3)
cd /data/app/mycat/conf
mv schema.xml schema.xml.ha
vim schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100"
dataNode="sh1">
<table name="user" dataNode="sh1"/>
<table name="order_t" dataNode="sh2"/>
</schema>
<dataNode name="sh1" dataHost="oldguo1" database= "taobao" />
<dataNode name="sh2" dataHost="oldguo2" database= "taobao" />
<dataHost name="oldguo1" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="1">
<heartbeat>select user()</heartbeat>
<writeHost host="db1" url="10.0.0.51:3307" user="root" password="123">
<readHost host="db2" url="10.0.0.51:3309" user="root"
password="123" />
</writeHost>
<writeHost host="db3" url="10.0.0.52:3307" user="root" password="123">
<readHost host="db4" url="10.0.0.52:3309" user="root"
password="123" />
</writeHost>
</dataHost>
<dataHost name="oldguo2" maxCon="1000" minCon="10" balance="1"
writeType="0" dbType="mysql" dbDriver="native" switchType="1">
<heartbeat>select user()</heartbeat>
<writeHost host="db1" url="10.0.0.51:3308" user="root" password="123">
<readHost host="db2" url="10.0.0.51:3310" user="root"
password="123" />
</writeHost>
<writeHost host="db3" url="10.0.0.52:3308" user="root" password="123">
<readHost host="db4" url="10.0.0.52:3310" user="root"
password="123" />
</writeHost>
</dataHost>
</mycat:schema>
创建测试库和表:
mysql -S /data/3307/mysql.sock -e "create database taobao charset utf8;"
mysql -S /data/3308/mysql.sock -e "create database taobao charset utf8;"
mysql -S /data/3307/mysql.sock -e "use taobao;create table user(id int,name
varchar(20))";
mysql -S /data/3308/mysql.sock -e "use taobao;create table order_t(id
int,name varchar(20))"
# 重启mycat
mycat restart
# mycat中对user 和 order 数据插入
mysql -uroot -p123456 -h10.0.0.51 -P8066 --defaultauth=mysql_native_password
insert into user values(1,'a');
insert into user values(2,'b');
insert into user values(3,'c');
commit;
insert into order_t values(1,'x'),(2,'y');
commit;
[root@db01 conf]# mysql -S /data/3307/mysql.sock -e "show tables from
taobao"
+------------------+
| Tables_in_taobao |
+------------------+
| user |
+------------------+
[root@db01 conf]# mysql -S /data/3308/mysql.sock -e "show tables from
taobao"
+------------------+
| Tables_in_taobao |
+------------------+
| order_t |
+------------------+
[root@db01 conf]# mysql -S /data/3307/mysql.sock -e "select * from
taobao.user"
+------+------+
| id | name |
+------+------+
| 1 | a |
| 2 | b |
| 3 | c |
+------+------+
[root@db01 conf]# mysql -S /data/3308/mysql.sock -e "select * from
taobao.order_t"
+------+------+
| id | name |
+------+------+
| 1 | x |
| 2 | y |
+------+------+
[root@db01 conf]#

7. Mycat 分布式架构–水平拆分

7.0 重要概念

1
2
3
4
5
6
7
8
分片策略 :几乎融合经典业务中大部分的分片策略。Mycat已经开发了相应算法,非常方便调用。
范围分片
取模
枚举
日期
HASH
等。
分片键: 作为分片条件的列。

7.1 范围分片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
比如说t3表
(1)行数非常多,2000w(1-1000w:sh1 1000w01-2000w:sh2)
(2)访问非常频繁,用户访问较离散
# 1. 修改schema.xml文件,定制分片策略
cp schema.xml schema.xml.1
vim schema.xml
添加:
<table name="t3" dataNode="sh1,sh2" rule="auto-sharding-long" />

# 2. 定义和使用分片策略
vim rule.xml
<tableRule name="auto-sharding-long">
<rule>
<columns>id</columns>
<algorithm>rang-long</algorithm>
</rule>

<function name="rang-long"
class="io.mycat.route.function.AutoPartitionByLong">
<property name="mapFile">autopartition-long.txt</property>
</function>

# 3. 定义范围
vim autopartition-long.txt
0-10=0
10-20=1

# 4. 创建测试表:
mysql -S /data/3307/mysql.sock -e "use taobao;create table t3 (id int not
null primary key auto_increment,name varchar(20) not null);"
mysql -S /data/3308/mysql.sock -e "use taobao;create table t3 (id int not
null primary key auto_increment,name varchar(20) not null);"

# 5. 测试:
重启mycat
mycat restart
mysql -uroot -p123456 -h 10.0.0.51 -P 8066
insert into t3(id,name) values(1,'a');
insert into t3(id,name) values(2,'b');
insert into t3(id,name) values(3,'c');
insert into t3(id,name) values(4,'d');
insert into t3(id,name) values(11,'aa');
insert into t3(id,name) values(12,'bb');
insert into t3(id,name) values(13,'cc');
insert into t3(id,name) values(14,'dd');
[root@db01 conf]# mysql -S /data/3308/mysql.sock -e "select * from
taobao.t3"
[root@db01 conf]# mysql -S /data/3307/mysql.sock -e "select * from
taobao.t3"

7.2 取模分片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
1%3 1
2%3 2
3%3 0
4%3 1
任何正整数数字和N(正整数)取模,得的值永远都是 0~N-1
id % 分片数量取模
N % 5 = 0-4 idx
取余分片方式:分片键(一个列)与节点数量进行取余,得到余数,将数据写入对应节点
# 1. 修改配置文件
vim schema.xml
<table name="t4" dataNode="sh1,sh2" rule="mod-long" />

# 2. 查看和定义分片使用
vim rule.xml
<property name="count">2</property>

# 3. 准备测试环境
创建测试表:
mysql -S /data/3307/mysql.sock -e "use taobao;create table t4 (id int not
null primary key auto_increment,name varchar(20) not null);"
mysql -S /data/3308/mysql.sock -e "use taobao;create table t4 (id int not
null primary key auto_increment,name varchar(20) not null);"
重启mycat
mycat restart

# 4. 测试:
mysql -uroot -p123456 -h10.0.0.51 -P8066
use TESTDB
insert into t4(id,name) values(1,'a');
insert into t4(id,name) values(2,'b');
insert into t4(id,name) values(3,'c');
insert into t4(id,name) values(4,'d');
insert into t4(id,name) values(6,'x'),(8,'y'),(10,'z');
分别登录后端节点查询数据
mysql -S /data/3308/mysql.sock -e "select * from taobao.t4"
mysql -S /data/3307/mysql.sock -e "select * from taobao.t4"

7.3 月份分片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
假设,tm (id int not null primary key,create_time datetime)
<tableRule name="sharding-by-month">
<rule>
<columns>create_time</columns>
<algorithm>partbymonth</algorithm>
</rule>
</tableRule>

<function name="partbymonth"
class="io.mycat.route.function.PartitionByMonth">
<property name="dateFormat">yyyy-MM-dd</property>
<property name="sBeginDate">2020-01-01</property>
</function

mysql -S /data/3307/mysql.sock -e "use taobao;create table tm (id int not
null primary key auto_increment,create_time datetime not null);"
mysql -S /data/3308/mysql.sock -e "use taobao;create table tm (id int not
null primary key auto_increment,create_time datetime not null);"
测试例子:

7.4 枚举分片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
t5 表
id name telnum
1 bj 1212
2 sh 22222
3 bj 3333
4 sh 44444
5 bj 5555

sharding-by-intfile

# 1. 设计分片策略
vim schema.xml
<table name="t5" dataNode="sh1,sh2" rule="sharding-by-intfile" />

# 2. 应用分片策略
vim rule.xml
<tableRule name="sharding-by-intfile">
<rule>
<columns>name</columns>
<algorithm>hash-int</algorithm>
</rule>
</tableRule>
<function name="hash-int"
class="org.opencloudb.route.function.PartitionByFileMap">
<property name="mapFile">partition-hash-int.txt</property>
<property name="type">1</property>
</function>

vim partition-hash-int.txt 配置:
bj=0
sh=1
DEFAULT_NODE=1

# 3. 准备测试环境
mysql -S /data/3307/mysql.sock -e "use taobao;create table t5 (id int not
null primary key auto_increment,name varchar(20) not null);"
mysql -S /data/3308/mysql.sock -e "use taobao;create table t5 (id int not
null primary key auto_increment,name varchar(20) not null);"
重启mycat
mycat restart

# 4. 插入测试数据:
mysql -uroot -p123456 -h10.0.0.51 -P8066
use TESTDB
insert into t5(id,name) values(1,'bj');
insert into t5(id,name) values(2,'sh');
insert into t5(id,name) values(3,'bj');
insert into t5(id,name) values(4,'sh');
insert into t5(id,name) values(5,'tj');

mysql -S /data/3308/mysql.sock -e "select * from taobao.t5"
mysql -S /data/3307/mysql.sock -e "select * from taobao.t5"

7.5 Mycat全局表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
a b c d .....
join
t

a
id name age

1 zs 18 sh1
id addr aid
1001 bj 1
1002 sh 2

2 ls 19 sh2
id addr aid
1001 bj 1
1002 sh 2

t
id addr aid
1001 bj 1
1002 sh 2

使用场景:
如果你的业务中有些数据类似于数据字典,比如配置文件的配置,
常用业务的配置或者数据量不大很少变动的表,这些表往往不是特别大,
而且大部分的业务场景都会用到,那么这种表适合于Mycat全局表,无须对数据进行切分,
要在所有的分片上保存一份数据即可,Mycat 在Join操作中,业务表与全局表进行Join聚合会优先选
择相同分片内的全局表join,
避免跨库Join,在进行数据插入操作时,mycat将把数据分发到全局表对应的所有分片执行,在进行数
据读取时候将会随机获取一个节点读取数据。

# 1. 设置全局表策略
vim schema.xml
<table name="t_area" primaryKey="id" type="global" dataNode="sh1,sh2" />

# 2. 后端数据准备
mysql -S /data/3307/mysql.sock -e "use taobao;create table t_area (id int
not null primary key auto_increment,name varchar(20) not null);"
mysql -S /data/3308/mysql.sock -e "use taobao;create table t_area (id int
not null primary key auto_increment,name varchar(20) not null);"
重启mycat
mycat restart

# 3. 测试:
mysql -uroot -p123456 -h10.0.0.51 -P8066
use TESTDB
insert into t_area(id,name) values(1,'a');
insert into t_area(id,name) values(2,'b');
insert into t_area(id,name) values(3,'c');
insert into t_area(id,name) values(4,'d');

mysql -S /data/3308/mysql.sock -e "select * from taobao.t_area"
mysql -S /data/3307/mysql.sock -e "select * from taobao.t_area"

7.6 E-R 分片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
a
join
b
on a.xx =b.yy

a
id name
1 a sh1
3 c

2 b sh2
4 d

b
id addr aid
1001 bj 1
1002 sh 2

1003 tj 3 sh2
1004 wh 4

为了防止跨分片join,可以使用E-R模式
<table name="a" dataNode="sh1,sh2" rule="mod-long">
<childTable name="b" joinKey="aid" parentKey="id" />
</table>

select * from a join b on a.id = b.aid where a.name=d

例子:
1. 修改配置文件
vim schema.xml
<table name="a" dataNode="sh1,sh2" rule="mod-long_oldguo">
<childTable name="b" joinKey="aid" parentKey="id" />
</table>

2. 修改rule.xml mod-log分片策略:
vim rule.xml
<tableRule name="mod-long_oldguo">
<rule>
<columns>id</columns>
<algorithm>mod-long_oldguo</algorithm>
</rule>
</tableRule>
<function name="mod-long_oldguo"
class="io.mycat.route.function.PartitionByMod">
<!-- how many data nodes -->
<property name="count">2</property>
</function>

3. 创建测试表
mysql -S /data/3307/mysql.sock -e "use taobao;create table a (id int not
null primary key auto_increment,name varchar(20) not null);"
mysql -S /data/3307/mysql.sock -e "use taobao;create table b (id int not
null primary key auto_increment,addr varchar(20) not null ,aid int );"

mysql -S /data/3308/mysql.sock -e "use taobao;create table a (id int not
null primary key auto_increment,name varchar(20) not null);"
mysql -S /data/3308/mysql.sock -e "use taobao;create table b (id int not
null primary key auto_increment,addr varchar(20) not null ,aid int );"


4. 重启mycat 测试
mycat restart
mysql -uroot -p123456 -h10.0.0.51 -P8066

use TESTDB
insert into a(id,name) values(1,'a'); 1 3308
insert into a(id,name) values(2,'b'); 0 3307
insert into a(id,name) values(3,'c'); 1 3308
insert into a(id,name) values(4,'d'); 0 3307
insert into a(id,name) values(5,'e'); 1 3308

insert into b(id,addr,aid) values(1001,'bj',1); 1 3308
insert into b(id,addr,aid) values(1002,'sj',3); 1 3308
insert into b(id,addr,aid) values(1003,'sd',4); 0 3307
insert into b(id,addr,aid) values(1004,'we',2); 0 3307
insert into b(id,addr,aid) values(1005,'er',5); 0 3307

========================================================
后端数据节点数据分布:
mysql -S /data/3307/mysql.sock -e "select * from taobao.a"
mysql -S /data/3307/mysql.sock -e "select * from taobao.b"
mysql -S /data/3308/mysql.sock -e "select * from taobao.a"
mysql -S /data/3308/mysql.sock -e "select * from taobao.b"

8. 管理类操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
[root@db01 conf]# mysql -uroot -p123456 -h10.0.0.51 -P9066
# 查看帮助
show @@help;
# 重新加载配置信息
reload @@config : schema.xml
reload @@config_all : 所有配置重新加载
rollback @@config | Rollback all config from memory

# sql监控分析功能,建议在做压测的时候关闭。
reload @@sqlstat=open | Open real-time sql stat analyzer
reload @@sqlstat=close | Close real-time sql stat analyzer

# 查看Mycat 服务情况
show @@server ;

# 查看分片DN节点信息
mysql> show @@datanode;
mysql> show @@datanode where schema = ?;

# 查看数据源
show @@datasource
show @@datasource where datanode=sh1;

# 报告心跳信息
show @@heartbeat
show @@heartbeat.detail where name=?
RS_CODE :
-1:连接失败
1 :连接正常
-2:连接超时
0 :初始化状态
如果节点故障,会有5次检测,失败后则状态为-1。
# 查看连接信息
show @@connection
# 关闭连接
kill @@connection id1,id2,...
# 查看后端连接
show @@backend
# 查看缓存应用情况
show @@cache;
# 查看sql统计
mysql> show @@sql;
mysql> show @@sql_slow;
mysql> show @@sql.sum;

9.其他管理

9.1 配置Mycat的日志管理

1
2
3
4
<asyncRoot level="info" includeLocation="true">
级别:All < Trace < Debug < Info < Warn < Error < Fatal < OFF

调试建议使用 Debug 级别,生产上一般使用 Info级别

9.2 配置Mycat的服务器参数

charset 属性

1
2
3
4
该属性用于字符集设置。
<system>
<property name="charset">utf8</property>
</system>

processors 属性

1
2
3
   该属性主要用于指定系统可用的线程数,默认值为机器 CPU 核心线程数。主要影响
processorBufferPool、 processorBufferLocalPercent、 processorExecutor 属性。
NIOProcessor 的个数也是由这个属性定义的,所以调优的时候可以适当的调高这个属性。

processorBufferChunk 属性

1
2
3
  该属性指定每次分配 Socket Direct Buffer 的大小,默认是 4096 个字节。这个属性也影响
buffer pool 的长度。如果一次性获取的数过大 buffer 不够用会经常出现警告,此时可以适当调
大。

processorBufferPool 属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
该属性指定 bufferPool 计算比例值。由于每次执行 NIO 读、写操作都需要使用到 buffer,
系统初始化的时候会建立一定长度的 buffer 池来加快读、写的效率,减少建立 buffer 的时间。
Mycat 中有两个主要的 buffer 池:

BufferPool:BufferPool 由 ThreadLocalPool 组合而成,每次从 BufferPool 中获
取 buffer 都会优先获取ThreadLocalPool 中的 buffer,未命中之后才会去获取 BufferPool
中的 buffer。也就是说 ThreadLocalPool 是作为 BufferPool 的二级缓存,每个线程内部
自己使用的。BufferPool 上的 buffer 则是每个 NIOProcessor 都共享的。这个属性的默认值
为:
默认bufferChunkSize(4096) * processors属性 * 1000
BufferPool 的总长度 = bufferPool / bufferChunk。
若 bufferPool 不是 bufferChunk 的整数倍,则总长度为前面计算得出的商 + 1

假设系统线程数为 4,其他都为属性的默认值,则:
bufferPool = 4096 * 4 * 1000
BufferPool 的总长度 : 4000 = 16384000 / 4096

processorBufferLocalPercent 属性:

1
2
3
4
5
6
7
8
9
10
前面提到了 ThreadLocalPool。这个属性就是用来控制分配这个 pool 的大小用的,这个属性
默认值为 100。

线程缓存百分比 = bufferLocalPercent / processors 属性。
例如,系统可以同时运行 4 个线程,使用默认值,则根据公式每个线程的百分比为 25。最后根据

这个百分比来计算出具体的 ThreadLocalPool 的长度公式如下:
ThreadLocalPool 的长度 = 线程缓存百分比 * BufferPool 长度 / 100
假设 BufferPool 的长度为 4000,其他保持默认值。
那么最后每个线程建立上的 ThreadLocalPool 的长度为: 1000 = 25 * 4000 / 100

心跳属性

1
2
3
4
5
6
7
8
9
10
11
mycat 中有几个周期性的任务来异步的处理一些我需要的工作。这些属性就在系统调优的过程中也是比
不可少的。

processorCheckPeriod :
清理 NIOProcessor 上前后端空闲、超时和关闭连接的间隔时间。默认是 1 秒,单位毫秒。

dataNodeIdleCheckPeriod :
对后端连接进行空闲、超时检查的时间间隔,默认是 300 秒,单位毫秒。

dataNodeHeartbeatPeriod :
对后端所有读、写库发起心跳的间隔时间,默认是 10 秒,单位毫秒。

服务相关属性

1
2
3
4
5
6
7
8
9
bindIp :
mycat 服务监听的 IP 地址,默认值为 0.0.0.0。

serverPort :
定义 mycat 的使用端口,默认值为 8066。

managerPort :
定义 mycat 的管理端口,默认值为 9066。

Mysql 连接相关属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
packetHeaderSize :
指定 Mysql 协议中的报文头长度。默认 4。
maxPacketSize :
指定 Mysql 协议可以携带的数据最大长度。默认 16M。
idleTimeout :
指定连接的空闲超时时间。某连接在发起空闲检查下,发现距离上次使用超过了空闲时间,那么这
个连接会被回收,就是被直接的关闭掉。默认 30 分钟,单位毫秒。

charset :
连接的初始化字符集。默认为 utf8。

txIsolation :
前端连接的初始化事务隔离级别,只在初始化的时候使用,后续会根据客户端传递过来的属性对后
端数据库连接进行同步。默认为 REPEATED_READ,设置值为数字默认 3。
READ_UNCOMMITTED = 1;
READ_COMMITTED = 2;
REPEATED_READ = 3;
SERIALIZABLE = 4;

sqlExecuteTimeout :
SQL 执行超时的时间,Mycat 会检查连接上最后一次执行 SQL 的时间,若超过这个时间则会直
接关闭这连接。默认时间为 300 秒,单位秒。

10.逻辑库配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# 总配置文件
schema.xml
<schema name="oldboy" checkSQLschema="false" sqlMaxLimit="100"
dataNode="sh1">
sh3
sh4
</schema>

# mycat 服务配置
server.xml
<user name="root" defaultAccount="true">
<property name="password">123456</property>
<property name="schemas">oldboy</property>
<property name="defaultSchema">oldboy</property>
<!--No MyCAT Database selected 错误前会尝试使用该schema作为

schema,不设置则为null,报错 -->

<!-- 表级 DML 权限设置 -->
<!--
<privileges check="false">
<schema name="TESTDB" dml="0110" >
<table name="tb01" dml="0000"></table>
<table name="tb02" dml="1111"></table>
</schema>
</privileges>
-->
</user>
<user name="user">
<property name="password">user</property>
<property name="schemas">oldboy</property>
<property name="readOnly">true</property>
<property name="defaultSchema">oldboy</property>
</user>
reload @@config_all : 所有配置重新加载

2. 添加一个逻辑库
schema.xml
<schema name="oldboy" checkSQLschema="false" sqlMaxLimit="100"
dataNode="sh1">
</schema>

server.xml
<property name="schemas">oldboy,oldguo</property>

reload @@config_all : 所有配置重新加载

11.sequence分布式全局序列

1
2
	在实现分库分表的情况下,数据库自增主键已经无法保证在集群中是全局唯一的主键了,因此
mycat提供了全局的sequence.

11.1 本地方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
采用该方式,mycat将sequence配置到classpath目录的sequence_conf.properties文件中,
在sequence_conf.properties文件做如下配置

GLOBAL_SEQ.HISIDS=
GLOBAL_SEQ.MINID=1001
GLOBAL_SEQ.MAXID=100000000
GLOBAL_SEQ.CURID=1000

其中HISIDS表示历史分段(一般无特殊需要则可以不配置),MINID表示最新的ID值,MAXID表示最
大的ID值,CURID表示当前的ID值。

0. 打开本地seq功能。
需要启用这种方式,则首先需要在server.xml中配置如下参数:
<system><property name="sequnceHandlerType">0</property></system>

配置测试:
1. 修改sequence_conf.properties
vim sequence_conf.properties
#全局seq
GLOBAL_SEQ.HISIDS=
GLOBAL_SEQ.MINID=1001
GLOBAL_SEQ.MAXID=10000000
GLOBAL_SEQ.CURID=1000
或者:自己定制
# self define sequence
OLDGUO.HISIDS=
OLDGUO.MINID=2001
OLDGUO.MAXID=20000000
OLDGUO.CURID=2000

2. 设置server.xml
<!--lang:java-->
public static final int SEQUENCEHANDLER_LOCALFILE = 0;
public static final int SEQUENCEHANDLER_MYSQLDB = 1;
public static final int SEQUENCEHANDLER_LOCAL_TIME = 2;
private int sequnceHandlerType = SEQUENCEHANDLER_LOCALFILE;

3.建表,插入数据测试
mysql> create table test(id int not null primary key ,name varchar(20));
Query OK, 0 rows affected (0.04 sec)
mysql> insert into test(id,name) values(next value for
MYCATSEQ_OLDGUO,@@hostname);
Query OK, 1 row affected (0.07 sec)
mysql>
mysql>
mysql> select * from test;
+-------+------+
| id | name |
+-------+------+
| 10001 | db02 |
+-------+------+
1 row in set (0.00 sec)

mysql> insert into test(id,name) values(next value for
MYCATSEQ_GLOBAL,@@hostname);
Query OK, 1 row affected (0.01 sec)
mysql> select * from test;
+-------+------+
| id | name |
+-------+------+
| 10001 | db02 |
| 10002 | db02 |
+-------+------+
2 rows in set (0.00 sec)

mysql> select * from test;
+-------+------+
| id | name |
+-------+------+
| 10001 | db02 |
| 10002 | db02 |
+-------+------+
2 rows in set (0.01 sec)

mysql> insert into test(id,name) values(next value for
MYCATSEQ_GLOBAL,@@hostname);
Query OK, 1 row affected (0.01 sec)
mysql> select * from test;
+-------+------+
| id | name |
+-------+------+
| 10001 | db02 |
| 10002 | db02 |
| 10003 | db02 |
+-------+------+

11.2 数据库方式

11.2.1 原理

1
2
	在数据库中建立一张表,存放 sequence 名称(name),sequence 当前值(current_value),步长
(increment int 类型每次读取多少个 sequence,假设为 K)等信息;

11.2.2 获取步骤

1
2
3
4
5
6
7
8
当初次使用该 sequence 时,根据传入的 sequence 名称,从数据库这张表中读取
current_value,和 increment 到 MyCat 中,并将数据库中的 current_value 设置为原
current_value 值+increment 值;

MyCat 将读取到 current_value+increment 作为本次要使用的 sequence 值,下次使用时,自
动加 1,当 使用 increment 次后,执行步骤 1)相同的操作. MyCat 负责维护这张表,用到哪些
sequence,只需要在这张表中插入一条记录即可。若某次读取的 sequence 没有用完,系统就停掉
了,则这次读取的 sequence 剩余值不会再使用。

11.2.3 配置细节

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# 修改Mycat配置文件server.xml
<property name="sequnceHandlerType">1</property>

# 修改Mycat配置文件schema.xml
<table name="t" primaryKey="id" autoIncrement="true" dataNode="sh1,sh2"
rule="mod-long"/>
<table name="MYCAT_SEQUENCE" primaryKey="name" dataNode="sh2"/>

# 修改Mycat 配置文件 sequence_db_conf.properties,
GLOBAL=sh2 --->修改
COMPANY=dn1
CUSTOMER=dn1
ORDERS=dn1

# 在sh2节点的 主 数据库中添加 MYCAT_SEQUENCE表
DROP TABLE IF EXISTS MYCAT_SEQUENCE;
CREATE TABLE MYCAT_SEQUENCE (name VARCHAR(50) NOT NULL,current_value INT
NOT NULL,increment INT NOT NULL DEFAULT 100, PRIMARY KEY(name))
ENGINE=InnoDB;
# 在dn2节点的 主库数据库中的 MYCAT_SEQUENCE 表插入sequence初始记录
insert into MYCAT_SEQUENCE(name,current_value,increment)
VALUES('GLOBAL',10000,100);
# 在dn2节点的 主数据库中创建存储过程
## 获取当前sequence的值:
DROP FUNCTION IF EXISTS mycat_seq_currval;
DELIMITER $
CREATE FUNCTION mycat_seq_currval(seq_name VARCHAR(50)) RETURNS varchar(64)
CHARSET utf8
DETERMINISTIC
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
DETERMINISTIC
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
DETERMINISTIC
BEGIN
UPDATE MYCAT_SEQUENCE
SET current_value = current_value + increment WHERE name = seq_name;
RETURN mycat_seq_currval(seq_name);
END $
DELIMITER ;

# 测试获取全局自增ID
mysql> insert into t4(id,name) values(NEXT VALUE FOR MYCATSEQ_GLOBAL,'zy')
;

11.3 时间戳方式

1
2
3
4
5
ID= 64 位二进制 (42(毫秒)+5(机器 ID)+5(业务编码)+12(重复累加)
server.xml:
<system><property name="sequnceHandlerType">2</property></system>
sequence_time_conf.properties:
WORKID=0-31 任意整数