Centos7.5部署MySQL5.7基于GTID主从复制+并行复制+半同步复制+读写分离(ProxySQL) 环境- 运维笔记 (完整版)

本文详细记录了在Centos7.5上部署MySQL5.7的全过程,包括基于GTID的主从复制、并行复制和半同步复制的配置,以及使用ProxySQL实现读写分离。文中介绍了GTID主从复制的优势,如避免数据不一致,简化故障转移,以及并行复制的实现原理和MySQL 5.7的组提交并行复制。此外,还涉及了半同步复制的两种模式及其优缺点,并给出了添加额外从库实现“一主两从”架构的步骤,最后通过ProxySQL配置了读写分离。
摘要由CSDN通过智能技术生成

一、实验环境

1

2

3

4

5

6

7

8

9

10

11

12

13

14

[root@mysql-master ~]# cat /etc/redhat-release

CentOS Linux release 7.5.1804 (Core)

 

为了方便实验,关闭所有节点的防火墙

[root@mysql-master ~]# systemctl stop firewalld

[root@mysql-master ~]# firewall-cmd --state

not running

 

[root@mysql-master ~]# cat /etc/sysconfig/selinux |grep "SELINUX=disabled"

SELINUX=disabled

[root@mysql-master ~]# setenforce 0              

setenforce: SELinux is disabled

[root@mysql-master ~]# getenforce                

Disabled

二、安装Mysql5.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

在三个mysql节点机上使用yum方式安装Mysql5.7,参考:https://www.cnblogs.com/kevingrace/p/8340690.html

  

安装MySQL yum资源库

[root@mysql-master ~]# yum localinstall https://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm

  

安装MySQL 5.7

[root@mysql-master ~]# yum install -y mysql-community-server

  

启动MySQL服务器和MySQL的自动启动

[root@mysql-master ~]# systemctl start mysqld.service

[root@mysql-master ~]# systemctl enable mysqld.service

  

设置登录密码

由于MySQL从5.7开始不允许首次安装后使用空密码进行登录!为了加强安全性,系统会随机生成一个密码以供管理员首次登录使用,

这个密码记录在/var/log/mysqld.log文件中,使用下面的命令可以查看此密码:

[root@mysql-master ~]# cat /var/log/mysqld.log|grep 'A temporary password'

2019-01-11T05:53:17.824073Z 1 [Note] A temporary password is generated for root@localhost: TaN.k:*Qw2xs

  

使用上面查看的密码TaN.k:*Qw2xs 登录mysql,并重置密码为123456

[root@mysql-master ~]# mysql -p                 #输入默认的密码:TaN.k:*Qw2xs

.............

mysql> set global validate_password_policy=0;

Query OK, 0 rows affected (0.00 sec)

  

mysql> set global validate_password_length=1;

Query OK, 0 rows affected (0.00 sec)

  

mysql> set password=password("123456");

Query OK, 0 rows affected, 1 warning (0.00 sec)

  

mysql> flush privileges;

Query OK, 0 rows affected (0.00 sec)

  

查看mysql版本

[root@mysql-master ~]# mysql -p123456

........

mysql> select version();

+-----------+

| version() |

+-----------+

| 5.7.24    |

+-----------+

1 row in set (0.00 sec)

 

=====================================================================

温馨提示

mysql5.7通过上面默认安装后,执行语句可能会报错:

ERROR 1819 (HY000): Your password does not satisfy the current policy requirements

 

这个报错与Mysql 密码安全策略validate_password_policy的值有关,validate_password_policy可以取0、1、2三个值:

解决办法:

set global validate_password_policy=0;

set global validate_password_length=1;

三、配置基于GTID的主从复制 

传统的基于binlog position复制的方式有个严重的缺点:如果slave连接master时指定的binlog文件错误或者position错误,会造成遗漏或者重复,
很多时候前后数据是有依赖性的,这样就会出错而导致数据不一致。

从MYSQL5.6开始,mysql开始支持GTID复制。GTID的全称是global transaction id,表示的是全局事务ID。GTID的分配方式为uuid:trans_id,其中:uuid是每个mysql服务器都唯一的,记录在$datadir/auto.cnf中。如果复制结构中,任意两台服务器uuid重复的话(比如直接冷备份时,auto.conf中的内容是一致的),在启动复制功能的时候会报错。这时可以删除auto.conf文件再重启mysqld。

基于GTID主从复制的优点大致有:
-  保证同一个事务在某slave上绝对只执行一次,没有执行过的gtid事务总是会被执行。
-  不用像传统复制那样保证binlog的坐标准确,因为根本不需要binlog以及坐标。
-  故障转移到新的master的时候很方便,简化了很多任务。
-  很容易判断master和slave的数据是否一致。只要master上提交的事务在slave上也提交了,那么一定是一致的。
-  当然,MySQL提供了选项可以控制跳过某些gtid事务,防止slave第一次启动复制时执行master上的所有事务而导致耗时过久。
-  虽然对于row-based和statement-based的格式都能进行gtid复制,但建议采用row-based格式。 

                                                              基于GTID主从复制环境部署记录                                                             

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

1)mysql-master主数据库上的操作

  

在my.cnf文件中配置GTID主从复制

[root@mysql-master ~]# cp /etc/my.cnf /etc/my.cnf.bak

[root@mysql-master ~]# >/etc/my.cnf

[root@mysql-master ~]# cat /etc/my.cnf

[mysqld]

datadir = /var/lib/mysql

socket = /var/lib/mysql/mysql.sock

  

symbolic-links = 0

  

log-error = /var/log/mysqld.log

pid-file /var/run/mysqld/mysqld.pid

  

#GTID:

server_id = 1

gtid_mode = on

enforce_gtid_consistency = on

    

#binlog

log_bin = mysql-bin

log-slave-updates = 1

binlog_format = row

sync-master-info = 1

sync_binlog = 1

   

#relay log

skip_slave_start = 1

  

配置后,记得重启mysql服务

[root@mysql-master ~]# systemctl restart mysqld

  

登录mysql,并查看master状态, 发现多了一项"Executed_Gtid_Set "

mysql> show master status;

+-------------------+----------+--------------+------------------+-------------------+

| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |

+-------------------+----------+--------------+------------------+-------------------+

| mysql-bin.000001 |      154 |              |                  |                   |

+-------------------+----------+--------------+------------------+-------------------+

1 row in set (0.00 sec)

  

mysql> show global variables like '%uuid%';

+---------------+--------------------------------------+

| Variable_name | Value                                |

+---------------+--------------------------------------+

| server_uuid   | 317e2aad-1565-11e9-9c2e-005056ac6820 |

+---------------+--------------------------------------+

1 row in set (0.00 sec)

  

查看确认gtid功能打开

mysql> show global variables like '%gtid%';

+----------------------------------+-------+

| Variable_name                    | Value |

+----------------------------------+-------+

| binlog_gtid_simple_recovery      | ON    |

| enforce_gtid_consistency         | ON    |

| gtid_executed                    |       |

| gtid_executed_compression_period | 1000  |

| gtid_mode                        | ON    |

| gtid_owned                       |       |

| gtid_purged                      |       |

| session_track_gtids              | OFF   |

+----------------------------------+-------+

8 rows in set (0.00 sec)

  

查看确认binlog日志功能打开

mysql> show variables like 'log_bin';

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| log_bin       | ON    |

+---------------+-------+

1 row in set (0.00 sec)

  

授权slave复制用户,并刷新权限

mysql> grant replication slave,replication client on *.* to slave@'172.16.60.212' identified by "slave@123";

Query OK, 0 rows affected, 1 warning (0.03 sec)

  

mysql> flush privileges;

Query OK, 0 rows affected (0.04 sec)

  

mysql> show grants for slave@'172.16.60.212';

+-------------------------------------------------------------------------------+

| Grants for slave@172.16.60.212                                                |

+-------------------------------------------------------------------------------+

| GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'172.16.60.212' |

+-------------------------------------------------------------------------------+

1 row in set (0.00 sec)

  

再次查看master状态

mysql> show master status;

+-------------------+----------+--------------+------------------+------------------------------------------+

| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                        |

+-------------------+----------+--------------+------------------+------------------------------------------+

| mysql-bin.000001 |      622 |              |                  | 317e2aad-1565-11e9-9c2e-005056ac6820:1-2 |

+-------------------+----------+--------------+------------------+------------------------------------------+

1 row in set (0.00 sec)

  

这里需要注意一下:

启动配置之前,同样需要对从服务器进行初始化。对从服务器初始化的方法基本和基于日志点是相同的,只不过在启动了GTID模式后,

在备份中所记录的就不是备份时的二进制日志文件名和偏移量了,而是记录的是备份时最后的GTID值。

    

需要先在主数据库机器上把目标库备份一下,假设这里目标库是kevin(为了测试效果,下面手动创建)

mysql> show databases;

+--------------------+

| Database           |

+--------------------+

| information_schema |

| mysql              |

| performance_schema |

| sys                |

+--------------------+

4 rows in set (0.00 sec)

  

mysql> CREATE DATABASE kevin CHARACTER SET utf8 COLLATE utf8_general_ci;

Query OK, 1 row affected (0.02 sec)

  

mysql> use kevin;

Database changed

mysql> create table if not exists haha (id int(10) PRIMARY KEY AUTO_INCREMENT,name varchar(50) NOT NULL);

Query OK, 0 rows affected (0.27 sec)

  

mysql> insert into kevin.haha values(1,"congcong"),(2,"huihui"),(3,"grace");   

Query OK, 3 rows affected (0.06 sec)

Records: 3  Duplicates: 0  Warnings: 0

  

mysql> select * from kevin.haha;

+----+----------+

id | name     |

+----+----------+

|  1 | congcong |

|  2 | huihui   |

|  3 | grace    |

+----+----------+

3 rows in set (0.00 sec)

  

把kevin库备份出来

[root@mysql-master ~]# mysqldump --single-transaction --master-data=2 --triggers --routines --databases kevin -uroot -p123456 > /root/kevin.sql

  

这里稍微注意下:

mysql5.6使用mysqldump备份时,指定备份的具体库,使用--database

mysql5.7使用mysqldump备份时,指定备份的具体库,使用--databases

  

[root@mysql-master ~]# ls /root/kevin.sql

/root/kevin.sql

[root@mysql-master ~]# cat /root/kevin.sql

-- MySQL dump 10.13  Distrib 5.7.24, for Linux (x86_64)

--

-- Host: localhost    Database: kevin

-- ------------------------------------------------------

-- Server version       5.7.24-log

.............

.............

--

-- GTID state at the beginning of the backup

--

  

SET @@GLOBAL.GTID_PURGED='317e2aad-1565-11e9-9c2e-005056ac6820:1-5';

  

然后把备份的/root/kevin.sql文件拷贝到mysql-slave1从数据库服务器上

[root@mysql-master ~]# rsync -e "ssh -p22" -avpgolr /root/kevin.sql root@172.16.60.212:/root/

  

==============================================================

2)mysql-slave1从数据库上的操作

  

在my.cnf文件中配置GTID主从复制

与主服务器配置大概一致,除了server_id不一致外,从服务器还可以在配置文件里面添加:"read_only=on" ,

使从服务器只能进行读取操作,此参数对超级用户无效,并且不会影响从服务器的复制;

[root@mysql-slave1 ~]# cp /etc/my.cnf /etc/my.cnf.bak

[root@mysql-slave1 ~]# >/etc/my.cnf

[root@mysql-slave1 ~]# vim /etc/my.cnf

[mysqld]

datadir = /var/lib/mysql

socket = /var/lib/mysql/mysql.sock

  

symbolic-links = 0

  

log-error = /var/log/mysqld.log

pid-file /var/run/mysqld/mysqld.pid

  

#GTID:

server_id = 2

gtid_mode = on

enforce_gtid_consistency = on

    

#binlog

log_bin = mysql-bin

log-slave-updates = 1

binlog_format = row

sync-master-info = 1

sync_binlog = 1

   

#relay log

skip_slave_start = 1

read_only = on

  

配置完成后,记得重启mysql服务

[root@mysql-slave1 ~]# systemctl restart mysqld

  

接着将主数据库目标库的备份数据kevin.sql导入到从数据库里

[root@mysql-slave1 ~]# ls /root/kevin.sql

/root/kevin.sql

[root@mysql-slave1 ~]# mysql -p123456

.........

mysql> show databases;

+--------------------+

| Database           |

+--------------------+

| information_schema |

| mysql              |

| performance_schema |

| sys                |

+--------------------+

4 rows in set (0.00 sec)

  

mysql> source /root/kevin.sql;

  

mysql> select * from kevin.haha;

+----+----------+

id | name     |

+----+----------+

|  1 | congcong |

|  2 | huihui   |

|  3 | grace    |

+----+----------+

3 rows in set (0.00 sec)

  

在从数据库里,使用change master 配置主从复制

mysql> stop slave;

Query OK, 0 rows affected, 1 warning (0.00 sec)

  

mysql> change master to master_host='172.16.60.211',master_user='slave',master_password='slave@123',master_auto_position=1;

Query OK, 0 rows affected, 2 warnings (0.26 sec)

  

mysql> start slave;

Query OK, 0 rows affected (0.02 sec)

  

mysql> show slave status \G;

*************************** 1. row ***************************

               Slave_IO_State: Waiting for master to send event

                  Master_Host: 172.16.60.211

                  Master_User: slave

                  Master_Port: 3306

                Connect_Retry: 60

              Master_Log_File: mysql-bin.000001

          Read_Master_Log_Pos: 1357

               Relay_Log_File: mysql-slave1-relay-bin.000002

                Relay_Log_Pos: 417

        Relay_Master_Log_File: mysql-bin.000001

             Slave_IO_Running: Yes

            Slave_SQL_Running: Yes

................

................

            Executed_Gtid_Set: 317e2aad-1565-11e9-9c2e-005056ac6820:1-5

                Auto_Position: 1

  

由上面可知,mysql-slave1节点已经和mysql-master节点配置了主从同步关系

  

3) mysql-master主数据库上进行状态查看和测试测试插入

  

mysql> show master status;

+-------------------+----------+--------------+------------------+------------------------------------------+

| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                        |

+-------------------+----------+--------------+------------------+------------------------------------------+

| mysql-bin.000001 |     1357 |              |                  | 317e2aad-1565-11e9-9c2e-005056ac6820:1-5 |

+-------------------+----------+--------------+------------------+------------------------------------------+

1 row in set (0.00 sec)

  

mysql> show slave hosts;

+-----------+------+------+-----------+--------------------------------------+

| Server_id | Host | Port | Master_id | Slave_UUID                           |

+-----------+------+------+-----------+--------------------------------------+

|         2 |      | 3306 |         1 | 2c1efc46-1565-11e9-ab8e-00505688047c |

+-----------+------+------+-----------+--------------------------------------+

1 row in set (0.00 sec)

  

mysql> insert into kevin.haha values(4,"beijing"),(5,"hefei"),(10,"xihu");

Query OK, 3 rows affected (0.06 sec)

Records: 3  Duplicates: 0  Warnings: 0

  

mysql> delete from kevin.haha where id<4;

Query OK, 3 rows affected (0.10 sec)

  

mysql> select * from kevin.haha;

+----+---------+

id | name    |

+----+---------+

|  4 | beijing |

|  5 | hefei   |

| 10 | xihu    |

+----+---------+

3 rows in set (0.00 sec)

  

4)mysql-slave1从数据库上查看

mysql> select * from kevin.haha;

+----+---------+

id | name    |

+----+---------+

|  4 | beijing |

|  5 | hefei   |

| 10 | xihu    |

+----+---------+

3 rows in set (0.00 sec)

  

发现mysql-slave1从数据库已经将新插入的数据同步过来了,由此,基于GTID的主从同步复制关系已经正常部署完成了!

四、并行复制 (解决主从复制延迟问题)

一般Mysql主从复制有三个线程参与,都是单线程:Binlog Dump(主) -> IO Thread (从) -> SQL Thread(从)。复制出现延迟一般出在两个地方:
-  SQL线程忙不过来 (可能需要应用数据量较大,可能和从库本身的一些操作有锁和资源的冲突;主库可以并发写,SQL线程不可以;主要原因)
-  网络抖动导致IO线程复制延迟(次要原因)。

MySQL主从复制延迟的解决办法:MySQL从5.6开始有了SQL Thread多个的概念,可以并发还原数据,即并行复制技术。并行复制的机制,是MySQL的一个非常重要的特性,可以很好的解决MySQL主从延迟问题!

在MySQL 5.6中,设置参数slave_parallel_workers = 4(>1),即可有4个SQL Thread(coordinator线程)来进行并行复制,其状态为:Waiting for an evant from Coordinator。但是其并行只是基于Schema的,也就是基于库的。如果数据库实例中存在多个Schema,这样设置对于Slave复制的速度可以有比较大的提升。通常情况下单库多表是更常见的一种情形,那基于库的并发就没有卵用。其核心思想是:不同schema下的表并发提交时的数据不会相互影响,即slave节点可以用对relay log中不同的schema各分配一个类似SQL功能的线程,来重放relay log中主库已经提交的事务,保持数据与主库一致。

MySQL 5.6版本支持所谓的并行复制,但是其并行只是基于schema的,也就是基于库的。如果用户的MySQL数据库实例中存在多个schema,对于从机复制的速度的确可以有比较大的帮助。但是基于schema的并行复制存在两个问题:
1) crash safe功能不好做,因为可能之后执行的事务由于并行复制的关系先完成执行,那么当发生crash的时候,这部分的处理逻辑是比较复杂的。
2) 最为关键的问题是这样设计的并行复制效果并不高,如果用户实例仅有一个库,那么就无法实现并行回放,甚至性能会比原来的单线程更差。而 单库多表是比多库多表更为常见的一种情形 。

注意:mysql 5.6的MTS是基于库级别的并行,当有多个数据库时,可以将slave_parallel_workers设置为数据库的数量,为了避免新建库后来回修改,也可以将该参数设置的大一些。设置为库级别的事务时,不允许这样做,会报错。

在MySQL 5.7中,引入了基于组提交的并行复制(官方称为Enhanced Multi-threaded Slaves,即MTS),设置参数slave_parallel_workers>0并且global.slave_parallel_type=‘LOGICAL_CLOCK’,即可支持一个schema下,slave_parallel_workers个的worker线程并发执行relay log中主库提交的事务。其核心思想:一个组提交的事务都是可以并行回放(配合binary log group commit);slave机器的relay log中 last_committed相同的事务(sequence_num不同)可以并发执行。其中,变量slave-parallel-type可以有两个值:1)DATABASE 默认值,基于库的并行复制方式;2)LOGICAL_CLOCK,基于组提交的并行复制方式;

MySQL 5.7开启Enhanced Multi-Threaded Slave很简单,只需要在Slave从数据库的my.cnf文件中如下配置即可:

1

2

3

4

5

6

# slave

 slave-parallel-type=LOGICAL_CLOCK

 slave-parallel-workers=8        #一般建议设置4-8,太多的线程会增加线程之间的同步开销

 master_info_repository=TABLE

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值