码迷,mamicode.com
首页 > 数据库 > 详细

趁一切还来得及【六】数据库MySQL读写分离与主主同步

时间:2015-01-01 23:57:27      阅读:616      评论:0      收藏:0      [点我收藏+]

标签:数据库   主主同步   半同步   授权分离   

相思相见知何日?此时此夜难为情。           
                                           --【唐】李白


第一章 数据库MySQL主从复制读写分离授权

1.1 主从复制读写分离方案简单分析

①数据库主从复制搭建之后,因为数据是单向的,因此默认规则就是所有的数据(主从相关收据)写入和更新都在主库上进行操作,避免主从同步的时候造成冲突。

②严格上来讲,从库上的非同步的库写入数据,只要和主库没有关系,也是可以写入的(或者作为主库),但是如果主从都想其中某个同步的库,写入数据,那么就会造成同步失败。

③读写分离的解决方案:

a、在从库上做用户授权控制

第一种方案:(前提主库不更新前提、开发角度)

主库:主库的主从同步用户授权更新写入权限(selectinsertdeleteupdate

从库:主库的web用户同步到主库,然后回收nsertdeleteupdate权限。

##不收回从库权限,在从库设置read-only只读。

第二种方案:(防止主库用户链接从库)

主库:主库的主从同步用户授权更新写入权限(selectinsertdeleteupdate

从库:新建一个用户,然后只给读权限(select)。

#在从库设置read-only只读,减少风险

第三种方案:(控制同步一部分库)

mysql库不同步的情况下,做授权

主库:主库的主从同步用户授权更新写入权限(selectinsertdeleteupdate

从库:主库的web用户同步到主库,然后回收nsertdeleteupdate权限。

##当从库切换主库的时候连接用户权限问题,因此需要保留一个从库专门准备接管主库。

第四种方案:在从库设置一个read-only参数

b、程序或代理软件实现,读指向从库,写指向主库

c、配置从库只能读不能写

d通过忽略授权表的方式防止写从库

#一个IP唯一标识一个主机,一台机器的不同的端口唯一标识一个的服务

1.2 忽略授权表的主从同步配置

mysql主从同步,默认是所有库所有表的复制同步(推荐)。可以通过忽略授权表,指定某个库或某个表的同步或不同步。

②主库和从库相关配置参数

Master端:
--binlog-do-db :#二进制日志记录的数据库(只记录什么,多个数据库用逗号分隔)
--binlog-ignore-do :#二进制日志忽略的数据库(忽略什么,多个数据库用逗号分隔)
Slave 端:
--replication-do-db :#设定需要复制的数据库(多库,逗号分隔)
--replication-ignore-db :#设定忽略复制的数据库(多库,逗号分隔)
--replication-do-table  :#设定需要复制的表(多表,逗号分隔)
--replication-ignore-table :#设定需要忽略复制的表(多表,逗号分隔)
--replication-wild-do-table  :#同--replication-do-table,但是可以加通配符
--replication-wild-ignore-table  :#同--replication-ignore-table ,可以加通配符

③注意在忽略创建的时候,一定要入库,才能真正的呗忽略过去。

[root@MySQL-01 ~]# grep binlog /data/3306/my.cnf 
binlog_cache_size = 1M
max_binlog_cache_size = 1M
max_binlog_size = 2M
binlog-ignore-db = mysql
binlog-ignore-db = performance_schema
binlog-ignore-db = information_schema
[root@MySQL-01 ~]# mysql -uroot -p123456 -S /data/3306/mysql.sock 
mysql> select user,host from mysql.user;
+------+---------------+
| user | host          |
+------+---------------+
| root | 127.0.0.1     |
| rep  | 192.168.109.% |
| root | localhost     |
+------+---------------+
3 rows in set (0.00 sec)
mysql> use mysql              ##=========》#解析:注意里,要想真正忽略,必须要进入库中进行创建,否则会造成忽略不通过。一定要入库。
Database changed
mysql> create user tslove@localhost identified by ‘123456‘;
Query OK, 0 rows affected (0.03 sec)
 
mysql> select user,host from mysql.user;                   
+--------+---------------+
| user   | host          |
+--------+---------------+
| root   | 127.0.0.1     |
| rep    | 192.168.109.% |
| root   | localhost     |
| tslove | localhost     |
+--------+---------------+
4 rows in set (0.00 sec)
#此时查看从库状态,从库无更新
mysql> select user,host from mysql.user;
+------+---------------+
| user | host          |
+------+---------------+
| root | 127.0.0.1     |
| rep  | 192.168.109.% |
| root | localhost     |
+------+---------------+
3 rows in set (0.00 sec)

1.3 数据库MySQL设置从库只读read-only

①修改从库配置文件在【mysqld】下面加如内容read-only,也可在启动的时候加如read-only参数限定从库只读。

read-only参数可以让slave服务器只接受slave服务器线程,会具有SUPER权限的用户的更新,可以确保slave服务器不接受来自普通用户的更新。启动的时候加上--read-only参数具有同样功能。

在实际应用中SUPERRsuper权限及all privileges权限)权限和root权限,不受此参数限制。

##主库进行建库,从库进行测试
主库:
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| d3306              |
| mysql              |
| performance_schema |
+--------------------+
4 rows in set (0.00 sec)
 
mysql> create database tset;    
Query OK, 1 row affected (0.00 sec)
 
mysql> show databases;      
+--------------------+
| Database           |
+--------------------+
| information_schema |
| d3306              |
| mysql              |
| performance_schema |
| tset               |
+--------------------+
5 rows in set (0.00 sec)
从库:
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| d3306              |
| mysql              |
| performance_schema |
| tset               |
+--------------------+
5 rows in set (0.00 sec)
###从库新增加用户进行测试
mysql>  grant create,select,insert,delete,update on *.* to tslove@localhost identified by ‘123456‘;##=========》#解析:普通用户进行登陆验证
 Query OK, 0 rows affected (0.04 sec)
mysql> select user,host from mysql.user;
+--------+---------------+
| user   | host          |
+--------+---------------+
| root   | 127.0.0.1     |
| rep    | 192.168.109.% |
| root   | localhost     |
| tslove | localhost     |
+--------+---------------+
4 rows in set (0.00 sec)
mysql> flush privileges; 
Query OK, 0 rows affected (0.00 sec)
[root@MySQL-02 ~]# mysql -utslove -p123456 -S /data/3306/mysql.sock 
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| d3306              |
| mysql              |
| performance_schema |
| tset               |
+--------------------+
5 rows in set (0.00 sec)
mysql> use tset;
Database changed
mysql> create table test(id int);
ERROR 1290 (HY000): The MySQL server is running with the --read-only option so it cannot execute this statement  ##=========》#解析:只读开启,不能更新数据
mysql> quit
Bye
###注释掉read-only参数或者删掉此参数
[root@MySQL-02 ~]# /data/3306/mysql stop
Stoping MySQL...
[root@MySQL-02 ~]# /data/3306/mysql start
Starting MySQL...
[root@MySQL-02 ~]# mysql -utslove -p123456 -S /data/3306/mysql.sock
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| d3306              |
| mysql              |
| performance_schema |
| tset               |
+--------------------+
5 rows in set (0.00 sec)
mysql> use tset
Database changed
mysql> create table mt(id int);    ##=========》#解析:此时可以进行库表更新
Query OK, 0 rows affected (0.11 sec)
mysql> select * from tset.mt;
+------+
| id   |
+------+
|    1 |
+------+
1 row in set (0.00 sec)
mysql> quit
Bye

1.4 MySQL主从复制故障模拟解决

MySQL从库数据冲突导致同步停止。

解决1:停止同步,SQL指针偏移1位。set global sql_slave_skip_counter =1,(注意数值越大丢的数据就越多)然后在打开同步开关。

#对于普通的互联网业务,忽略问题不是很大,要考虑不影响相关业务的前提。针对于读写分离的互联网业务,如果解决主从同步比主从数据不一致对当前更重要,可以使用此种解决方法。如果主从数据一致也很重要,那么就在找个时间点,进行数据比对恢复。(根据业务选择处理

解决2:配置文件中加入slave-skip-errors = 1032,1062,1007(逗号隔开多个错误代码) 由于入库重复,导致错误,选择忽略。错误代码可以由slave服务器的错误日志中或show slave status\G 中获取到。

#######################################问题:数据冲突导致主从同步停止
#解决方法一、(SQL指针偏移)
①从库操作:
[root@MySQL-02 ~]# mysql -uroot -p123456 -S /data/3306/mysql.sock    ##=========》#解析:#从库冲突故障
mysql> create database chongtu;
Query OK, 1 row affected (0.00 sec)
mysql> show slave status \G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.109.165
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000013
          Read_Master_Log_Pos: 190
               Relay_Log_File: relay-bin.000026
                Relay_Log_Pos: 253
        Relay_Master_Log_File: mysql-bin.000013
             Slave_IO_Running: Yes  ##=========》#解析:此时查看同步是正常的
            Slave_SQL_Running: Yes
(以下略)
1 row in set (0.00 sec)
②主库操作
[root@MySQL-01 ~]# mysql -uroot -p123456 -S /data/3306/mysql.sock 
mysql> create database chongtu;
Query OK, 1 row affected (0.00 sec)
③从库查看状态
mysql> show slave status \G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.109.165
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000013
          Read_Master_Log_Pos: 279
               Relay_Log_File: relay-bin.000026
                Relay_Log_Pos: 253
        Relay_Master_Log_File: mysql-bin.000013
             Slave_IO_Running: Yes     ##=========》#解析:从库同步状态错误
            Slave_SQL_Running: No
              Replicate_Do_DB: 
          Replicate_Ignore_DB: mysql
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 1007
                   Last_Error: Error ‘Can‘t create database ‘chongtu‘; database exists‘ on query. Default database: ‘chongtu‘. Query: ‘create database chongtu‘                       ##=========》#解析:具体报错信息
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 190
              Relay_Log_Space: 492
              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: 1007     ##=========》#解析:错误代号:数据库已存在,创建数据库失败。多利用错误
               Last_SQL_Error: Error ‘Can‘t create database ‘chongtu‘; database exists‘ on query. Default database: ‘chongtu‘. Query: ‘create database chongtu‘                      ##=========》#解析:最后一次同步报错信息
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 1
1 row in set (0.00 sec)
#问题解决
mysql> stop slave;
Query OK, 0 rows affected (0.01 sec)
 
mysql> set global sql_slave_skip_counter =1; ##=========》#解析:忽略执行1个更新,这个数值可以根据需要进行调整。(错误的数量)
Query OK, 0 rows affected (0.04 sec)
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
mysql> show slave status \G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.109.165
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000013
          Read_Master_Log_Pos: 279
               Relay_Log_File: relay-bin.000027
                Relay_Log_Pos: 253
        Relay_Master_Log_File: mysql-bin.000013
             Slave_IO_Running: Yes           ##=========》#解析:错误问题得到解决
            Slave_SQL_Running: Yes
(以下忽略)
1 row in set (0.00 sec)
#解决方法二、(调过错误号)
mysql> system cat /data/3306/my.cnf
(信息显示部分)
skip-name-resolve
slave-skip-errors = 1032,1062,1007
#注意修改配置文件需要重启从库数据库才能生效
#skip-name-resolve #这个参数就是mysql链接慢,可以使用次参数,忽略名字解析。提高链接速度。
#需要注意的是-slave-skip-errors=all一般不要使用。
 
#其他可能引起数据库主从不同步的原因:
1)mysql自身的原因
2)不同的数据库版本引起的不同步,低版本到高版本可以,但是高版本不能向低版本同步。

1.5 MySQL从库记录binlog的方法

需要记录binlog的情况:

①当前的从库还要作为其他的从库的主库(级联同步)

②把当前的从库作为数据库备份服务器时候开启binlog日志。

配置:打开log-bin

在从库的配置文件中增加参数:

log-bin = /data/3306/mysql-bin

log-slave-updates

③指定bin-log的保存天数

expire_logs_days = 7 #解析指定bin-log日志的自动保留天数,多余的自动删除。一般设定3-7天。

##主库和从库都可以使用的参数,这个参数就相当于

find /data/3306/ -type -name "mysql-bin.000*" -mtime +7|xargs rm -f

④拓展:数据库硬盘坏了如何恢复数据

1)找一台新设备,先回复全备的数据

2)恢复上一次全备时间点带之后当前时间点的所有增量bin-log日志内容。

##所以实际生产中,除了定时的全备之外,还要及时的备份binlog日志文件(inotify或者定时任务每分钟推送binglog日知道备份服务器)。

[root@MySQL-02 ~]# vim  /data/3306/my.cnf 
[root@MySQL-02 ~]# egrep "log-bin|log-slave"  /data/3306/my.cnf     
log-bin = /data/3306/mysql-bin
log-slave-updates
[root@MySQL-02 ~]# /data/3306/mysql stop
Stoping MySQL...
[root@MySQL-02 ~]# /data/3306/mysql start
Starting MySQL...
Starting MySQL...
[root@MySQL-02 ~]# ll /data/3306/
总用量 600
drwxr-xr-x 7 mysql mysql   4096 1月   1 18:59 data
-rw-r--r-- 1 mysql mysql   1930 1月   1 18:58 my.cnf
-rwx------ 1 root  root    1307 12月 23 11:49 mysql
-rw-rw---- 1 mysql mysql    809 12月 27 16:03 mysql-bin.000001        ##=========》#解析:查看此时已经生成binlog日志文件
-rw-rw---- 1 mysql mysql     84 1月   1 18:59 mysql-bin.index
-rw-rw---- 1 mysql mysql      5 1月   1 18:59 mysqld.pid
-rw-r----- 1 mysql root   35466 1月   1 18:59 mysql_oldboy3306.err
srwxrwxrwx 1 mysql mysql      0 1月   1 18:59 mysql.sock
-rw-rw---- 1 mysql mysql    150 1月   1 18:59 relay-bin.000028
-rw-rw---- 1 mysql mysql    253 1月   1 18:59 relay-bin.000029
-rw-rw---- 1 mysql mysql     56 1月   1 18:59 relay-bin.index
-rw-rw---- 1 mysql mysql     54 1月   1 18:59 relay-log.info

1.6 数据库MySQL一主多从宕机切换方案

主库宕机的问题,一定要预案处理流程,一般有两种情况,服务器宕机,数据库宕机。

①首先进去主库以外的从库,查看进程:show processlist;主要查看State状态信息(IO线程和SQL线程状态)

②根据信息,如果提示从库已经同步等待下一次更新状态(等待),那么就是说已经完全同步。

③如果数据出现没有同步完成的情况,需要查看从库的master-info文件,看那一个从库的(pos差距)位置点最大、同步更靠前更新,与主库的一致性更高,丢的数据越少。

④选择POS最大的。数据同步最靠前的从库作为主库,进行切换。

⑤另外一种解决办法,半同步的话,直接进行切换。

⑥如果只是mysql服务宕机,服务器还能起来,那么在从库上把主库的bin-log拉过来进行补全。根据位置点信息缺失的数据进行补全。然后提升为主库。

主库切换的时候注意事项:

1)确保所有的relay-log全部更新完毕。(查看状态:读完所有的relay-log

2)配置文件检查:

#检查授权表以及类似read-only参数,如果配置了read-only或者log-slave-updates等作为主库相冲突的参数要清理注释一下。打开bin-log

3)重启从库mysql服务,登录执行操作:stop slave;之后retset master;然后退出。

4)进入数据库目录,删除master.info relay-log.info文件

⑧如果主库服务器没有宕机,需要拉取bin-log日志进行从库的补全。

⑨注意如果已经做了mysql半同步,那么直接半同步的mysql提升为主库。(半同步功能)

如果是从库的slave宕机:就重新做一个从库解决。(实际生产中slave至少要2-3个)

1)停止slave服务,直接灌回全备的数据,

2change master ...

3)检查更新配置文件,开启start slave

4)查看检查主从状态。

####注意解决问题的思路,实现有准备,有问题根据预案进行解决。

第二章 数据库MySQL异步复制与半同步

1、异步复制的缺点:

MySQL复制默认是异步复制,Master将事件写入binlog,但并不知道Slave是否或何时已经接收且已处理。在异步复制的机制的情况下,如果Master宕机,事务在Master上已提交,但很可能这些事务没有传到任何的Slave上。假设有Master->Salve故障转移的机制,此时Slave也可能会丢失事务。

2、半同步复制的概念:

a、当Slave主机连接到Master时,能够查看其是否处于半同步复制的机制。

b、当Mster上开启半同步复制的功能时,至少应该有一个Slave开启其功能。此时,一个线程在Master上提交事务将受到阻塞,直到得知一个已开启半同步复制功能的Slave已收到此事务的所有事件,或等待超时

c当一个事务的事件都已写入其relay-log中且已刷新到磁盘上,Slave才会告知已收到。

d、如果等待超时,也就是Master没被告知已收到,此时Master会自动转换为异步复制的机制。当至少一个半同步的Slave赶上了,Master与其Slave自动转换为半同步复制的机制。

e、半同步复制的功能要在MasterSlave都开启,半同步复制才会起作用;否则,只开启一边,它依然为异步复制。

3、同步,异步,半同步复制的比较:

同步复制:Master提交事务,直到事务在所有的Slave都已提交,此时才会返回客户端,事务执行完毕。缺点:完成一个事务可能会有很大的延迟。

异步复制:当Slave准备好才会向Master请求binlog。缺点:不能保证一些事件都能够被所有的Slave所接收。

半同步复制:半同步复制工作的机制处于同步和异步之间,Master的事务提交阻塞,只要一个Slave已收到该事务的事件且已记录。它不会等待所有的Slave都告知已收到,且它只是接收,并不用等其完全执行且提交

#########################################################控制变量
Variable Name Variable Scope Dynamic Variable Type Default Effect Host 
rpl_semi_sync_master_enabled Global Yes boolean OFF Master 
rpl_semi_sync_slave_enabled Global Yes boolean OFF Slave 
rpl_semi_sync_master_timeout Global Yes numeric 10000 Master 
#解释:
rpl_semi_sync_master_enabled#是控制Master是否开启半同步,开启或不开启,将其设置为ON或OFF(1or0).
rpl_semi_sync_master_timeout#是控制Master等待多长时间被告知Slave已收到,也就是所谓的超时时间。
rpl_semi_sync_slave_enabled#是控制Slave是否开启半同步,开启或不开启,将其设置为ON或OFF(1or0)。
#监控半同步复制的状态变量(几个常用的)
Rpl_semi_sync_master_clients:#查看有多少个开启半同步复制的插件的Slave
Rpl_semi_sync_master_status:#查看在Master上半同步复制是否正在运行,其值为ON时,说明Master已启用半同步且已被告知有Slave收到;其值为OFF时,说明Master没启用半同步或是没被告知,由于timeout等原因。
Rpl_semi_sync_master_no_tx:#查看有多少事务没有用半同步复制的机制进行复制。
Rpl_semi_sync_master_yes_tx:#查看有多少事务是通过半同步复制机制成功复制。
Rpl_semi_sync_slave_status:#查看Slave上半同步复制是否正常运行,其值为ON时,说明Slave正通过半同步复制且Slave I/O正在运行;为OFF时,反之。
#说明关于其它的请参阅:http://dev.mysql.com/doc/refman/5.5/en/index.html
#半同步复制的安装,配置 http://www.linuxidc.com
 
#########################################################环境要求:
a、MySQL5.5或以上版本
b、在MySQL上安装插件需要数据库支持动态载入。检查是否支持,用如下检测:
mysql> show global variables like ‘have_dynamic_loading‘;
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| have_dynamic_loading | YES  |
+----------------------+-------+
1 row in set (0.00 sec)
c、半同步复制是基于复制的环境。也就是说配置半同步复制前,已有复制的环境。
#########################################################安装:
#在Master上执行:
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME ‘semisync_master.so‘;
#各个Slave上执行:
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME ‘semisync_slave.so‘;
#如果不清楚Plugin的目录,用如下查找:
mysql> show global variables like ‘plugin_dir‘;
+---------------+----------------------------------+
| Variable_name | Value                            |
+---------------+----------------------------------+
| plugin_dir    | /opt/usr/local/mysql/lib/plugin/ |
+---------------+----------------------------------+
#检查Plugin是否已正确安装:
mysql> show plugins;
or
mysql> select * from information_schema.plugins;
#配置:
#在Master上执行:
mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;
mysql> SET GLOBAL rpl_semi_sync_master_timeout = N;
#在Slave上执行:
mysql> SET GLOBAL rpl_semi_sync_slave_enabled = 1;
#说明:http://www.linuxidc.com
#如果在一个正在运行的Slave上开启半同步复制的功能,必须先停止Slave I/O,将其启用半同步后,再开启Slave I/O.
mysql> STOP SLAVE IO_THREAD; START SLAVE IO_THREAD;
#如果不这样做,Slave还是会以异步的方式进行复制。
#正如大家所知,如果不将变量的设置写到配置文件,下次重启数据库,将失效。写入配置文件:
Master上:
[mysqld]
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=1000 # 1 second
Slave上:
[mysqld]
rpl_semi_sync_slave_enabled=1
 
#总结:半同步复制个人感觉是维持数据完整性,安全性的的一个策略,虽会损失一点性能,还是值得的。配置很简单,关键是理解其工作机制。
参考博文:http://www.linuxidc.com/Linux/2013-06/86627.htm

第三章 数据MySQL的主主(多主)同步

3.1 主主同步配置实践

①写两个主,搭建主主同步,互为主从能够分担主库的压力。每个主下面还可以挂从库,提供服务。(一般不推荐)

②需要配置的参数:【mysqld】下面配置(主键自增

log-bin = /data/3306/mysql-bin

log-slave-updates

以上两个参数是需要打开的。

#主库:Master:1
#m1(10.0.0.240 3306)#________m-m m1 start________auto_increment_increment        = 2         ##=========》#解析:ID的自增间隔定义,如1 3 5间隔为2.auto_increment_offset           = 1           ##=========》#解析:ID的初始位置#(形成1 3 5 7序列)
#主库:Master:2
auto_increment_increment        = 2         ##=========》#解析:ID的自增间隔定义,如2 4 6间隔为2.auto_increment_offset           = 2           ##=========》#解析:ID的初始位置#(形成2 4 6 8序列)
#这样两边同时写入的时候,不会导致冲突。
#注意,插入数据的时候,当主库1写入到1,3,5的时候,主库2的写入开始从6开始6,8,10。然后主库1再从11开始数据的写入。
#所以以上写入的数据ID可能是不连续的。

③需要打开配置文件中的相关参数:(不同的就是自增的起始值)

auto_increment_increment = 2
auto_increment_offset = x
log-bin = /data/3306/mysql-bin
log-slave-updates

##双主同步,互为主从。

④使用主主的前提:表的主键需要自增,或者使用程序来指定ID自增分配来写库(M1:1 3 5 M2:2 4 6)。前者用的广泛,现在基本上表都是自增的。

⑤三台以上的主主,环状同步,讲ID间隔值设为3,注意都是单向的不要双向同步。

⑥高可用参考:http://oldboy.blog.51cto.com/2561410/1240412

#主库1
[root@MySQL-01 ~]# vi /data/3306/my.cnf 
auto_increment_increment = 2              ##=========》#解析:如果是环状的3个,那么此处修改为3就可以。(1,4,7)
auto_increment_offset = 1
log-bin = /data/3306/mysql-bin            ##=========》#解析:注意主主同步,需要开启log-bin和updates
log-slave-updates
[root@MySQL-01 ~]# /data/3306/mysql stop 
Stoping MySQL...
[root@MySQL-01 ~]# /data/3306/mysql start
Starting MySQL...
#主库2
[root@MySQL-02 ~]# vi /data/3306/my.cnf
auto_increment_increment = 2
auto_increment_offset = 1
log-bin = /data/3306/mysql-bin
log-slave-updates
[root@MySQL-02 ~]# /data/3306/mysql stop
Stoping MySQL...
[root@MySQL-02 ~]# /data/3306/mysql start
Starting MySQL...
[root@MySQL-02 ~]# mysqldump -uroot -p123456 -S /data/3306/mysql.sock -A -B --master-data=1 -x -E >/data/backup/mysql_bk/zhuzhu3307bak.sql ##=========》#解析:锁表备份数据,实际中如果两台主库数据是完全同步的可以不做如此导入。
##将备份的数据导入到主库1.
#主库1
[root@MySQL-01 ~]# mysql -uroot -p123456 -S /data/3306/mysql.sock < /data/backup/mysql_bk/zhuzhu3307bak.sql 
[root@MySQL-01 ~]# mysql -uroot -p123456 -S /data/3306/mysql.sock
mysql> CHANGE MASTER TO 
    -> MASTER_HOST=‘192.168.109.166‘,
    -> MASTER_PORT=3306,          
    -> MASTER_USER=‘rep‘,         
    -> MASTER_PASSWORD=‘123456‘;
Query OK, 0 rows affected (0.01 sec)
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
 
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.109.166
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000005
          Read_Master_Log_Pos: 1251
               Relay_Log_File: relay-bin.000005
                Relay_Log_Pos: 253
        Relay_Master_Log_File: mysql-bin.000005
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: mysql
           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: 1251
              Relay_Log_Space: 549
              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: 0
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: 3
1 row in set (0.00 sec)
######进行测试
mysql> create database tslove;
Query OK, 1 row affected (0.00 sec)
mysql> create database tslove;
mysql> use tslove
Database changed
Query OK, 1 row affected (0.00 sec)
mysql> create table student(
    -> id int(4) not null AUTO_INCREMENT,
    -> name char(20) not null,
    -> primary key(id)
    -> );
Query OK, 0 rows affected (0.01 sec)
mysql> insert into student(name) values(‘oldboy1‘);
Query OK, 1 row affected (0.00 sec)
mysql> insert into student(name) values(‘oldboy3‘);
Query OK, 1 row affected (0.00 sec)
mysql> select * from tslove.student;  ##=========》#解析:注意此处的掺入数据的ID值   
+----+---------+
| id | name    |
+----+---------+
|  1 | oldboy1 |
|  3 | oldboy2 |
|  5 | oldboy3 |
+----+---------+
3 rows in set (0.00 sec)
 
#主库2
[root@MySQL-02 ~]# mysql -uroot -p123456 -S /data/3306/mysql.sock 
mysql> select * from tslove.student;   ##=========》#解析:主库1上的额数据已经同步过来
+----+---------+
| id | name    |
+----+---------+
|  1 | oldboy1 |
|  3 | oldboy2 |
|  5 | oldboy3 |
+----+---------+
3 rows in set (0.00 sec)
mysql> insert into student(name) values(‘oldgirl1‘);
Query OK, 1 row affected (0.01 sec)
 
mysql> insert into student(name) values(‘oldgirl2‘);
Query OK, 1 row affected (0.02 sec)
 
mysql> insert into student(name) values(‘oldgirl3‘);
Query OK, 1 row affected (0.01 sec)
###主库1再次插入数据
mysql> use tslove
Database changed
mysql> insert into student(name) values(‘oldboy4‘);
Query OK, 1 row affected (0.00 sec)
 
mysql> insert into student(name) values(‘oldboy5‘);
Query OK, 1 row affected (0.00 sec)
 
mysql> select * from tslove.student;               
+----+----------+
| id | name     |
+----+----------+
|  1 | oldboy1  |
|  3 | oldboy2  |
|  5 | oldboy3  |
|  7 | oldgirl1 |
|  9 | oldgirl2 |
| 11 | oldgirl3 |
| 13 | oldboy4  |
| 15 | oldboy5  |
+----+----------+
8 rows in set (0.00 sec)
#############以上就是当参数都是auto_increment_increment = 2 auto_increment_offset = 1的时候的数据插入
##下面修改主2上面的auto_increment_offset = 2,进行测试
#主库2
[root@MySQL-02 ~]# vi /data/3306/my.cnf
auto_increment_increment = 2 
auto_increment_offset = 2 
[root@MySQL-02 ~]# /data/3306/mysql stop
Stoping MySQL...
[root@MySQL-02 ~]# /data/3306/mysql start
Starting MySQL...
[root@MySQL-02 ~]# mysql -uroot -p123456 -S /data/3306/mysql.sock 
mysql> create table student2(
    -> id int(4) not null AUTO_INCREMENT,    ##=========》#解析:自增建表
    -> name char(20) not null,
    -> primary key(id)
    -> );
Query OK, 0 rows affected (0.02 sec)
mysql> show tables;
+------------------+
| Tables_in_tslove |
+------------------+
| student          |
| student2         |
+------------------+
2 rows in set (0.00 sec)
#主库1
mysql> insert into student2(name) values(‘tslove1‘); 
Query OK, 1 row affected (0.00 sec)
 
mysql> insert into student2(name) values(‘tslove2‘);
Query OK, 1 row affected (0.00 sec)
 
mysql> insert into student2(name) values(‘tslove3‘);
Query OK, 1 row affected (0.00 sec)
mysql> select * from tslove.student2;              
+----+---------+
| id | name    |
+----+---------+
|  1 | tslove1 |
|  3 | tslove2 |
|  5 | tslove3 |
+----+---------+
3 rows in set (0.00 sec)
#主库2
mysql> insert into student2(name) values(‘ts1‘);   
Query OK, 1 row affected (0.00 sec)
 
mysql> insert into student2(name) values(‘ts2‘);
Query OK, 1 row affected (0.01 sec)
 
mysql> select * from tslove.student2;
+----+---------+
| id | name    |
+----+---------+
|  1 | tslove1 |
|  3 | tslove2 |
|  5 | tslove3 |                       
|  6 | ts1     |                               ##=========》#解析:注意此处插入数据的ID值已经变化
|  8 | ts2     |
+----+---------+
5 rows in set (0.00 sec)
###所以在实际应用中插入的数据可能是不连续的,但是不会对业务产生影响。
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.109.165
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000015
          Read_Master_Log_Pos: 5949
               Relay_Log_File: relay-bin.000036
                Relay_Log_Pos: 985
        Relay_Master_Log_File: mysql-bin.000015
             Slave_IO_Running: Yes        ##=========》#解析:链接状态参考值(两个YES)         
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: mysql
           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: 5949
              Relay_Log_Space: 1135
              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: 0          ##=========》#解析:同步数据延迟时间
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: 1
1 row in set (0.00 sec)
##主主同步状态正常,双写部署完成。

3.2 增删改差记录(待补充)

①②③④⑤⑥⑦⑧⑨⑩


参考文章:

linux运维老男孩培训老师博客
http://oldboy.blog.51cto.com/all/2561410


本文出自 “燁未央_Estelle” 博客,请务必保留此出处http://tslove.blog.51cto.com/9115838/1598331

趁一切还来得及【六】数据库MySQL读写分离与主主同步

标签:数据库   主主同步   半同步   授权分离   

原文地址:http://tslove.blog.51cto.com/9115838/1598331

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!