天天看点

MySQL主从复制、主从复制(异步)、半同步复制、SSL复制

概述

    复制通常用来创建主节点的副本,通过添加冗余节点来保证高可用性,当然复制也可以用于其他 用途,例如在从节点上进行数据读、分析等等。在横向扩展的业务中,复制很容易实施,主要表现在在利用主节点进行写操作,多个从节点进行读操作,在mysql5.5中默认为异步复制。

    mysql 复制的异步性是指:事物首先在主节点上提交,然后复制给从节点并在从节点上应用,这样意味着在同一个时间点主从上的数据可能不一致,异步复制的好处在于它 比同步复制要快,如果对数据的一致性要求很高,还是采用同步复制较好。

    mysql-5.5 开始支持semi-synchronous的复制,也叫半同步复制,目的在于事务环境下保持主从一致

    mysql-5.6 开始支持延时复制。

    mysql复制的原理现阶段都是一样的,master将操作记录到bin-log中,slave的一个线程去master读取bin-log,并将他们保存到relay-log中,slave的另外一个线程去重放relay-log中的操作来实现和master数据同步。

MySQL主从复制、主从复制(异步)、半同步复制、SSL复制

    该过程的第一部分就是master记录二进制日志。在每个事务更新数据完成之前,master在二日志记录这些改变。MySQL将事务串行的写入二进制日志,即使事务中的语句都是交叉执行的。在事件写入二进制日志完成后,master通知存储引擎提交事务。

    下一步就是slave将master的binary log拷贝到它自己的中继日志。首先,slave开始一个工作线程——I/O线程。I/O线程在master上打开一个普通的连接,然后开始binlog dump process。Binlog dump process从master的二进制日志中读取事件,如果已经跟上master,它会睡眠并等待master产生新的事件。I/O线程将这些事件写入中 继日志。

    SQL slave thread(SQL从线程)处理该过程的最后一步。SQL线程从中继日志读取事件,并重放其中的事件而更新slave的数据,使其与master中的数 据一致。只要该线程与I/O线程保持一致,中继日志通常会位于OS的缓存中,所以中继日志的开销很小。

    此外,在master中也有一个工作线程:和其它MySQL的连接一样,slave在master中打开一个连接也会使得master开始一个线程。复制 过程有一个很重要的限制——复制在slave上是串行化的,也就是说master上的并行更新操作不能在slave上并行操作。

异步主从复制配置

准备:

    OS:rhel5.8_i386

    SoftWare: mysql-5.5.28-linux2.6-i686.tar.gz

1、主从安装mysql

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

tar

xf mysql-5.5.28-linux2.6-i686.

tar

.gz -C 

/usr/local/

# cd /usr/local/

# ln -s mysql-5.5.28-linux2.6-i686/ mysql

# groupadd -r mysql

# useradd -r -g mysql -s /sbin/nologin mysql

# mkdir /mydata/data -p

# chown -R mysql.mysql /mydata/data/

# chown -R root.mysql /usr/local/mysql/*

# cp support-files/my-large.cnf /etc/my.cnf

# cp support-files/mysql.server  /etc/init.d/mysqld

[mysqld]

innodb_file_per_table = 1

datadir = 

/mydata/data

#由于是二进制安装的mysql所以必须指定数据库目录位置

# vim /etc/profile.d/mysqld.sh

export

PAHT=$PATH:

/usr/local/mysql/bin

# . /etc/profile.d/mysqld.sh

2、主服务器配置

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

# vim /etc/my.cnf

[mysqld]

log-bin = master-bin

log-bin-index = master-bin.index

server-

id

= 1

# scripts/mysql_install_db --user=mysql --datadir=/mydata/data/

# service mysqld start

# mysql

mysql> grant replication slave on *.* to repl@

'192.168.100.12'

identified by 

'asdasd'

;

mysql> flush privileges;

mysql> flush logs;

mysql> show master logs;

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

| Log_name          | File_size |

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

| master-bin.000001 |     27326 |

| master-bin.000002 |   1038693 |

| master-bin.000003 |       379 |

| master-bin.000004 |       107 |

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

mysql> purge binary logs to 

'master-bin.000004'

;

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

# vim /etc/my.cnf

[mysqld]

relay-log = relay-log

relay-log-index = relay-log.index

read

-only = 1

#innodb_file_per_table = 1

#binlog_format=mixed

server-

id

= 10

# scripts/mysql_install_db --user=mysql --datadir=/mydata/data/

# service mysqld start

mysql> change master to master_host=

'192.168.100.11'

,master_user=

'repl'

,master_password=

'asdasd'

,master_log_file=

'master-bin.000004'

,master_log_pos=107;

mysql> show slave status\G

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

Slave_IO_State: 

Master_Host: 192.168.100.11

Master_User: repl

Master_Port: 3306

Connect_Retry: 60

Master_Log_File: master-bin.000004

Read_Master_Log_Pos: 107

Relay_Log_File: relay-log.000001

Relay_Log_Pos: 4

Relay_Master_Log_File: master-bin.000004

Slave_IO_Running: No

Slave_SQL_Running: No

Replicate_Do_DB: 

Replicate_Ignore_DB: 

Replicate_Do_Table: 

Replicate_Ignore_Table: 

Replicate_Wild_Do_Table: 

Replicate_Wild_Ignore_Table: 

Last_Errno: 0

Last_Error: 

Skip_Counter: 0

Exec_Master_Log_Pos: 107

Relay_Log_Space: 107

Until_Condition: None

Until_Log_File: 

Until_Log_Pos: 0

Master_SSL_Allowed: No

Master_SSL_CA_File: 

Master_SSL_CA_Path: 

Master_SSL_Cert: 

Master_SSL_Cipher: 

Master_SSL_Key: 

Seconds_Behind_Master: NULL

Master_SSL_Verify_Server_Cert: No

Last_IO_Errno: 0

Last_IO_Error: 

Last_SQL_Errno: 0

Last_SQL_Error: 

Replicate_Ignore_Server_Ids: 

Master_Server_Id: 0

1 row 

in

set

(0.00 sec)

mysql> start slave;

mysql> show slave status\G

Slave_IO_Running: Yes

Slave_SQL_Running: Yes

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

    至此主从异步复制就完成了

    说明:

        slave_id 必须是唯一的

        slave没有必要开启二进制日志,但在有些情况下必须设置,如mysql级联. slave为其它slave的master,所以要设置bin_log,默认为hostname,但如果hostname改变则会出问题。

        有些人可能开启了slave二进制日志,却没有设置log_slave_updates,然后查看slave的数据是否改变,这是错误的配置。所以尽量使用read_only = 1 ,防止改变数据(除了sql_thread进程)。

        start slave :启动从服务器IO_Thread和SQL_Thread线程,这里也可以单独对它们进行启动

        在主服务器上需设置sync-binlog = 1 ,用于事务安全

        重置change master参数:

1 2 3

mysql> slave stop;

mysql> reset slave;

mysql> change master to master_host=

'192.168.100.11'

,master_user=

'repl'

,master_password=

'asdasd'

,master_log_file=

'master-bin.000005'

,master_log_pos=107;

        由于slave都会自动连接上master,当我们有时需要手动调整时可以在启动前移动slave数据目录下的master.ino和relay.info文件,或者查看variables中有无“skip-slave-start”变量,有就设置为ON

半同步复制

    /usr/local/mysql/lib/plugin/semisync_master.so

    /usr/local/mysql/lib/plugin/semisync_slave.so

    1、主服务器配置

1 2 3 4 5 6 7 8 9 10 11 12

mysql> install plugin rpl_semi_sync_master soname 

'semisync_master.so'

;

mysql> show variables like 

'%semi%'

;

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

| Variable_name                      | Value |

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

| rpl_semi_sync_master_enabled       | OFF   |

| rpl_semi_sync_master_timeout       | 10000 |

| rpl_semi_sync_master_trace_level   | 32    |

| rpl_semi_sync_master_wait_no_slave | ON    |

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

mysql> set global rpl_semi_sync_master_enabled=1;

mysql> set global rpl_semi_sync_master_timeout=1000;

    2、Slave上配置

1 2 3 4 5 6 7 8 9

mysql> install plugin rpl_semi_sync_slave soname 

'semisync_slave.so'

;

mysql> show variables like 

'%semi%'

;

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

| Variable_name                   | Value |

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

| rpl_semi_sync_slave_enabled     | OFF   |

| rpl_semi_sync_slave_trace_level | 32    |

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

mysql> set global rpl_semi_sync_slave_enabled=1;

    如果需要永久生效,请将上面几个变量分别写入master与slave中mysqld字段中。

MySQL复制过滤

    MySQL复制过滤可以在Master,也可以在Slave

    由于基于Master的过滤操作为影响到二进制日志的完整性,对于我们以后做及时点还原会有影响,所以我们一般不建议在Maser上做复制过滤。

    1、基于数据库

1 2

binlog-

do

-db           

//binlog-do-db

表示和哪个数据库相关的写入类、修改类指令会被写入

binlog-ignore-db        

//binlog-ignore-db

表示忽略(黑名单)

    2、基于表

    replicate-do-table=

    replicate-ignore-table=

    3、对于表,还可以用通配符配置过滤

    replicate-wild-do-table=

    replicate-wild-ignore-table=

SSL复制

    要求主从服务器各自都要有证书和私钥;默认情况下主从服务器的SSL功能是没有启用的,需要先启用。

1 2 3 4 5 6 7 8 9 10 11 12

mysql> show variables like 

'%ssl%'

;

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

| Variable_name | Value    |

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

| have_openssl  | DISABLED |

| have_ssl      | DISABLED |

| ssl_ca        |          |

| ssl_capath    |          |

| ssl_cert      |          |

| ssl_cipher    |          |

| ssl_key       |          |

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

1、配置Master为CA证书服务器

1 2 3 4 5 6 7 8 9 10 11 12 13

# vim /etc/pki/tls/openssl.cnf

# cd /etc/pki/CA/

# (umask 077; openssl genrsa 1024 >private/cakey.pem)

# openssl req -new -x509 -key private/cakey.pem -out cacert.pem

Country Name (2 letter code) [GB]:CN 

State or Province Name (full name) [Berkshire]:GD

Locality Name (eg, city) [Newbury]:ZS

Organization Name (eg, company) [My Company Ltd]:NEO

Organizational Unit Name (eg, section) []:tech

Common Name (eg, your name or your server's 

hostname

) []:station01.neo.com

# mkdir newcerts certs crl

# touch index.txt

# echo 01 >serial

2、为Master上的MySQL准备私钥以及颁发证书

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

# mkdir /usr/local/mysql/ssl

# cd /usr/local/mysql/ssl/

#(umask 077; openssl genrsa 1024 > mysql.key)

# openssl req -new -key mysql.key -out mysql.csr -days 3650

Country Name (2 letter code) [GB]:CN

State or Province Name (full name) [Berkshire]:GD

Locality Name (eg, city) [Newbury]:ZS

Organization Name (eg, company) [My Company Ltd]:NEO

Organizational Unit Name (eg, section) []:tech

Common Name (eg, your name or your server's 

hostname

) []:station01.neo.com

Email Address []:

Please enter the following 

'extra'

attributes

to be sent with your certificate request

A challenge password []:

An optional company name []:

# openssl ca -in mysql.csr -out mysql.crt

Using configuration from 

/etc/pki/tls/openssl

.cnf

Check that the request matches the signature

Signature ok

Certificate Details:

Serial Number: 1 (0x1)

Validity

Not Before: May 28 02:26:17 2014 GMT

Not After : May 28 02:26:17 2015 GMT

Subject:

countryName               = CN

stateOrProvinceName       = GD

organizationName          = NEO

organizationalUnitName    = tech

commonName                = station01.neo.com

X509v3 extensions:

X509v3 Basic Constraints: 

CA:FALSE

Netscape Comment: 

OpenSSL Generated Certificate

X509v3 Subject Key Identifier: 

A4:B7:A6:98:9F:60:08:BE:86:87:65:5F:B6:13:BC:4A:5B:D4:44:3A

X509v3 Authority Key Identifier: 

keyid:4F:D8:57:42:D9:39:17:7D:39:44:91:01:A4:01:DE:32:92:D6:F9:DF

Certificate is to be certified 

until

May 28 02:26:17 2015 GMT (365 days)

Sign the certificate? [y

/n

]:y

1 out of 1 certificate requests certified, commit? [y

/n

]y

Write out database with 1 new entries

Data Base Updated

# chown mysql.mysql *

3、Slave上申请证书

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

# mkdir /usr/local/mysql/ssl

# (umask 077; openssl genrsa 1024 >mysql.key)

# openssl req -new -key mysql.key -out mysql.csr -days 3650

Country Name (2 letter code) [GB]:CN

State or Province Name (full name) [Berkshire]:GD

Locality Name (eg, city) [Newbury]:ZS

Organization Name (eg, company) [My Company Ltd]:NEO

Organizational Unit Name (eg, section) []:tech

Common Name (eg, your name or your server's 

hostname

) []:station02.neo.com

Email Address []:

Please enter the following 

'extra'

attributes

to be sent with your certificate request

A challenge password []:

An optional company name []:

# scp mysql.csr 192.168.100.11:/root/

4、Master上为Slave签发证书

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

# openssl ca -in mysql.csr -out mysql.crt

Using configuration from 

/etc/pki/tls/openssl

.cnf

Check that the request matches the signature

Signature ok

Certificate Details:

Serial Number: 2 (0x2)

Validity

Not Before: May 28 02:36:24 2014 GMT

Not After : May 28 02:36:24 2015 GMT

Subject:

countryName               = CN

stateOrProvinceName       = GD

organizationName          = NEO

organizationalUnitName    = tech

commonName                = station02.neo.com

X509v3 extensions:

X509v3 Basic Constraints: 

CA:FALSE

Netscape Comment: 

OpenSSL Generated Certificate

X509v3 Subject Key Identifier: 

81:9F:5B:E7:06:D0:64:B7:E6:81:3F:98:95:71:D4:DF:C6:B8:CE:3D

X509v3 Authority Key Identifier: 

keyid:4F:D8:57:42:D9:39:17:7D:39:44:91:01:A4:01:DE:32:92:D6:F9:DF

Certificate is to be certified 

until

May 28 02:36:24 2015 GMT (365 days)

Sign the certificate? [y

/n

]:

yes

1 out of 1 certificate requests certified, commit? [y

/n

]

yes

Write out database with 1 new entries

Data Base Updated

# scp mysql.crt 192.168.100.12:/usr/local/mysql/ssl/

# scp /etc/pki/CA/cacert.pem 192.168.100.12:/usr/local/mysql/ssl/

5、Master上编缉/etc/my.cnf启用ssl,并设置主从

1 2 3 4 5 6 7 8 9 10

# vim /etc/my.cnf

[mysqld] 

log-bin=mysql-bin 

sync_binlog = 1                          

##二进制日志 

server-

id

= 1                            

##此id必须全局唯一 

innodb_flush_log_at_trx_commit=1         

##每秒将事务日志立刻刷写到磁盘 

ssl                                      

##启用ssl默认是不开启的,mysql中show variables like '%ssl%'查看 

ssl_ca =

/usr/local/mysql/ssl/cacert

.pem      

##ca文件的位置 

ssl_cert= 

/usr/local/mysql/ssl/mysql

.crt     

##证书文件的位置 

ssl_key = 

/usr/local/mysql/ssl/mysql

.key     

##私钥文件的位置

6、启动mysql,并查看ssl信息

1 2 3 4 5 6 7 8 9 10 11 12 13 14

# service mysqld start 

# mysql 

mysql> show variables like 

'%ssl%'

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

| Variable_name | Value                           | 

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

| have_openssl  | YES                             | 

| have_ssl      | YES                             | 

| ssl_ca        | 

/usr/local/mysql/ssl/cacert

.pem | 

| ssl_capath    |                                 | 

| ssl_cert      | 

/usr/local/mysql/ssl/mysql

.crt  | 

| ssl_cipher    |                                 | 

| ssl_key       | 

/usr/local/mysql/ssl/mysql

.key  | 

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

7、为同步建立一最小权限账户,并要求ssl

1 2 3 4 5

mysql> create user 

'backup_ssl'

@

'192.168.100.12'

identified by 

'redhat'

mysql> revoke all privileges,grant option from 

'backup_ssl'

@

'192.168.100.12'

mysql> grant replication slave,replication client on *.* to 

'backup_ssl'

@

'192.168.100.12'

require ssl; 

mysql> flush privileges;

mysql> flush logs;

8、Slave上编缉/etc/my.cnf,启用ssl,并设置主从

1 2 3 4 5 6 7 8 9 10 11

# vim /etc/my.cnf

[mysqld] 

server-

id

= 2                        

##此id必须全局唯一 

##log-bin = mysql-bin                ##注释掉,从服务器不需要二进制日志

relay-log = mysql-relay              

##中继日志 

relay-log-index = mysql-ralay.index  

##中继目录 

read

-only = 1                        

##从服务器只读

ssl                                  

##启用ssl默认是不开启的,mysql中show variables like '%ssl%'查看 

ssl_ca =

/usr/local/mysql/ssl/cacert

.pem  

##ca文件的位置 

ssl_cert= 

/usr/local/mysql/ssl/mysql

.crt 

##证书文件的位置 

ssl_key = 

/usr/local/mysql/ssl/mysql

.key 

##私钥文件的位置

9、启用mysqld并查看ssl相关信息

1 2 3 4 5 6 7 8 9 10 11 12 13

# servie mysqld start 

mysql> show variables like 

'%ssl%'

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

| Variable_name | Value                           | 

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

| have_openssl  | YES                             | 

| have_ssl      | YES                             | 

| ssl_ca        | 

/usr/local/mysql/ssl/cacert

.pem | 

| ssl_capath    |                                 | 

| ssl_cert      | 

/usr/local/mysql/ssl/mysql

.crt  | 

| ssl_cipher    |                                 | 

| ssl_key       | 

/usr/local/mysql/ssl/mysql

.key  | 

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

10、启动slave同步进程,连接主服务器

1 2 3 4 5 6 7 8 9 10 11

mysql> change master to  

-> master_host=

'192.168.100.11'

-> master_user=

'backup_ssl'

-> master_password=

'redhat'

-> master_log_file=

'mysql-bin.000004'

-> master_ssl=1, 

-> master_ssl_ca=

'/usr/local/mysql/ssl/cacert.pem'

-> master_ssl_cert=

'/usr/local/mysql/ssl/mysql.crt'

-> master_ssl_key=

'/usr/local/mysql/ssl/mysql.key'

mysql> start slave 

mysql> show slave status\G; 

##查看slave状态

11、关注以下参数:

1 2 3 4 5 6 7 8

Slave_IO_Running: Yes                                  

##IOthread是否运行,如果为No代表slave运行不正常 

Slave_SQL_Running: Yes                                 

##SQLthread是否运行,如果为No代表slave运行不正常 

Master_SSL_CA_File: 

/usr/local/mysql/ssl/cacert

.pem    

##是否启用了ssl 

Master_SSL_Cert: 

/usr/local/mysql/ssl/mysql

.crt 

Master_SSL_Key: 

/usr/local/mysql/ssl/mysql

.key 

Master_Log_File: mysql-bin.00005                       

##最后接收的主服务器的二进制 

Exec_Master_Log_Pos: 338                               

##最后执行的位置,查看master中是不是该位置 

Last_IO_Errno: 0                                       

##最后一次IOthread有没有报错