mysqlAB复制
mysql主从复制有利于数据库的健壮性、提升访问速度和易于维护管理。
总结:
从库上配置账户、ip、用户名、密码、链接文件的位置、pos点,在从库上同步数据前要把主库之前的数据导入到从库,然后在实行数据同步。
开启开关之前,主从库数据要一致
在打开开关之前要在主库上建立授权,链接从库的账号
主库必须要打开bin-log开关
要启动 start slave;来开始同步
dns主-----> dns从 非实时
mysql主------------------> mysql从 实时
延时是很严重的问题
mysql replication
mysql AB 复制技术(主从) 原理非常类似 oracle dataguard oracle DG (dataguard)
MySQL支持单向、异步复制,复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器。
同步复制需要使用ndb(各集群节点都可读可写)或者drbd(网络raid)这些技术,或者是新版mysql的半同步复制
异步 优点:主速度快 缺点:数据可能主从不同步
同步 优点和缺点和异步正好相反
mysql主 ----------> mysql从
create table aaa;
bin-log --------> relay-bin-log
io
sql create table aaa;
把主上的二进制日志(bin-log)的内容传到从上的一个新的日志叫relay-bin-log
从上的 IO 线程 负责传输
从上的 SQL 线程 负责从服务器解析日志
由两个线程 去进行复制的过程 IO线程 sql线程 (以前只使用一个线程,两个是改进后才有的)
复制的过程:
1,slave端的IO线程连上master端,请求
2,master端返回给slave端,bin log文件名和位置信息
3,IO线程把master端的bin log内容依次写到slave端relay bin log里,并把master端的bin-log文件名和位置记录到master.info里。
4,salve端的sql线程,检测到relay bin log中内容更新,就会解析relay log里更新的内容,并执行这些操作;也就是说salve执行和master一样的操作而达到数据同步的目的;
=============================================================================
AB复制前准备
1,准备两台机器
2,安装两台全新的mysql(这里使用rpm版,方便,源码版可以课后自行做测试;两台版本最好一致,不一致可能会有兼容性问题) yum -y install mysql*
3,主机名配置及其绑定(两台互相绑定)
vim /etc/hosts (主机名和ip相互绑定只绑自己的)
4,时间同步
5,防火墙,selinux关闭
准备两台虚拟机:最好是全新
master ---- slave
172.16.14.2 172.16.14.3
第一步;改配置文件,并重启服务
# vim /etc/my.cnf
master上 (主文件)
[mysqld]
log-bin=mysql-bin 二进制日志必须打开
server-id=2
slave上 (副文件)
[mysqld]
server-id=3
/etc/init.d/mysqld restart 用脚本重启
第二步:主授权 在主文名字是主到 ip写从到
master上授权,super和replication slave都是复制要用的权限
mysql> grant super,replication slave on *.* to 'li'@'172.16.14.X' identified by '123'; 在主授权给从的ip地址,让他以主到身份登录 li代表的是主机名
mysql> flush privileges;
第三步:查看master的正在写的二进制文件名和位置
mysql> show master status; --只有打开二进制日志,这句命令才有结果,表示当前数据库的二进制日志写到什么位置
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000003 | 473 | | |
+------------------+----------+--------------+------------------+
第四步:在slave(从)上连接master(主),并指定从哪个position开始复制
在(从端操作)下面
mysql> change master to
-> master_user='li', --对应前面主授权时的用户
-> master_password='123', --对应前面主授权时的密码
-> master_host='172.16.14.2', --主的IP
-> master_port=3306, --端口,如果为3307就要换成3307
-> master_log_file='mysql-bin.000003', --主上面查到的文件名
-> master_log_pos=473; --主上面查到的位置号
这部报错的话把stop slave; 切记必须关掉之后在修改,然后启动
mysql> start slave;
mysql> show slave status\G 查看表
......
Slave_IO_Running: Yes
Slave_SQL_Running: Yes --这两人个线程为yes,代表集群搭建成功
......
=============================================================================
问题一:
思考几种情况下做复制的区别:
1, 业务还没有上线的情况,全新安装的mysql做复制
2,主已经跑了一年,一直都有开着二进制日志,并且日志无丢失
直接从一年前的起始位置开始复制(但要注意初始化的数据不要重复初始化的数据)
3,主已经跑了一年,但没有打开二进制日志
骤一:master打开二进制日志,重启
步骤二:master全备,并恢复到slave(假设要30分钟)
步骤三;30分钟后,slave从备份的position开始复制
4, 主以前跑了半年没打开二进制日志,后半年打开了二进制日志,你现在要做从
骤一:master全备,并恢复到slave(假设要30分钟)
步骤二;30分钟后,slave从备份的position开始复制
主 从
.000001 1
跑了一年 跑了一年的数据
现在 .000054 563 563
备份恢复 30分钟
.000054 800
问题二:
主要打开二进制日志,从要不要开二进制日志?
从mysql可开可不开,要看情况
问题三:
主和从的读写情况怎么做?
从不能写,从只能读;主可读可写;
所以有些时候做主只写,从只读,也就是读写分离
问题四:
我做了读写分离的一主一从的架构,请问我前端的程序(web,游戏,业务等)如何来访问数据库?
如果装前端web(假设phpwind),填写数据库的IP为主的IP,那么这种情况,
mysql从就完全变成了一个实时备份的服务器,所有的读写全在主上
所以要在前端程序和数据库之间加入代理层程序,也就是填写的数据库IP不是主的也不是从的,
而是代理的,由代理来负责把写操作给主,读操作给从
客户
|
|
web程序,游戏程序(c,php,java.......)
|
|
代理层(中间件)(mysqlproxy,amoeba,cobar,mycat)
|
|
mysql主 ----> mysql从
问题五:
关于单点故障的问题,如果从挂掉了,怎么解决?如果主挂掉了,怎么解决?
从挂掉,再恢复的过程图:
代理
mysql主 ----> mysql从
写 读
从挂了
写读
很久之后,从要启动,启动之前可以手动写防火墙,让代理访问不到从
启动,会自动连主,主会把这段时间写的复制给从
复制完后,手动确认(可以在从启动前在主上show master status;查看主写到哪了.然后在从上可以show slave status查看写到主的postion或者这个positsion之后,则表示数据都复制过来了),然后去掉防火墙
代理发现从OK了,会把读给从
写 读
主挂掉,再恢复的过程图:(这样最好做双主,右边的主平时正常情况然后做只读的从,只在左边的主挂了,才会做写操作)
代理
mysql主 <----> mysql从(打开二进制日志)
写 读
主挂了
写 读
很久之后,主要启动,启动之前手动写防火墙,让代理访问不到主
主启动,自动连上后,因为是双主,从可以把这段时间写的复制回主
复制完后,手动确认,然后去掉主上的防火墙
代理发现主OK了,会把写给回主
写 读
=============================================================================
一主一从
关于另几种架构的探讨:
一主多从
-- salve
master -- salve
-- salve
--适合于以读为主的业务,使用多个salve分担读的压力,但要注意的是这种架构,salve越多,那么master复制的压力就越大(成本增大)
多主一从 --这种架构不支持
主A phpwind
从C
主B discuz
双主架构 master A <--> master B
phpwind主 discuz主
上面已经讨论了双主架构的一个用法(就是一个平时仍然为主,另一个平时为从,只在主挂了才会去从上写)
1,会循环复制吗?
他们不会循环复制,因为做复制时会指定ID值,并且不一致
2,两边真的能同时写相同的数据吗?
可能会有问题
如下表所示:
时间点 master A master B
1 id=1改为id=2
2 id=1改为id=3
3 master A的改变复制过来,并解析,id会又改为2
4 master B的改变复制过来并解析,id又会改为3
问题产生,数据不一致
3,两边可以写不同的数据吗?
可以
可以通过业务程序层,指定一些表的写操作全在一端,另一些表的写操作全在另一端,也就是说两边不会同时写相同的表(当然这是理想状态,因为业务复杂的话会有表的联结等情况)
然后通过指定mysql复制的参数,一部分表或库会从A复制到B,另外一部分表或库从B复制到A就可以避免上面的问题了
或者两个库,一个库master A来写,另一个库master B来写
数据切分
------------------------------------------------------
master C
| |
环型架构 master A -- master B
--不可行
------------------------------------------------------
-- salve
级联架构 master -- salve -- salve
-- salve
为了解决一主多从的master的复制压力
可以把slave做为下一级从机的master
增加复制的级联层次,造成的延迟更长
所以这种架构并不是很推荐,一般会进行分拆集群
--------------------------------------------------
双主和级联合起来
master ----salve --slave
|
| -- slave
master ---salve -- slave
-- slave
-----------------------------------------------------
优化原则:分
大型结构的数据量太大,要用到数据切分(水平,垂直)
mysqlproxy
amoeba
cobar
=============================================================================
一主多从的做法
就是上面的步骤有几个从就做几次
双主架构的做法:
反着做一遍就行
级联架构
master -slave -slave
我的结构图
master A slave B slave C
172.16.14.2 172.16.14.3 172.16.14.4
sever-id=2 server-id=3 server-id=4
log-bin=master log-bin=mid-slave
log-slave-updates=1
bin-log relay-bin-log relay-bin-log
bin-log ------> relay-bin-log
打开log-slave-updates=1
让第一台传过来relay日志记录
到自己的二进制日志
bin-log -------> relay-bin-log
练习:
实现下面的结构图(这里包括了一主一从,一主多从,双主,级联架构)
mysql1 《----》 mysql2 ----》 mysql3
=============================================================================
半同步复制
MySQL的默认复制其实是异步操作,而不是同步,也就意味着允许主从之间的数据存在一
定的延迟,mysql当初这样设计的目的也是基于可用性的考虑,为了保证master
不受slave的影响,并且异步复制使得master处于一种性能最优的状态:
写完binlog后即可提交而不需要等待slave的操作完成。这样存在一个隐患,当你使用slave作为备份时
如果master挂掉,那么会存在部分已提交的事务未能成功传输到slave的可能,这就意味着数据丢失!
mysql 主 ---- mysql从
所谓的半同步复制就是master每commit一个事务,要slave应用这个事物后回给master信号。这样master才能把事物成功commit。这样就保证了master-slave的数据绝对的一致(但是以牺牲master的性能为代价).但等待时间也是可以调整的。
mysql半同步复制等待时间超时后(默认时间为10秒),会自动转换成异步复制
=========================================
搭建环境 两台虚拟机
master -- slave
先安装mysql5.5之后的版本,因为这个版本之后才实现的半同步复制
第一大步:
先要搭建好mysqlAB异步复制
过程省略
第二大步:在异步基础上转成半同步复制
1,在master上安装这个插件
master> install plugin rpl_semi_sync_master soname 'semisync_master.so';
Query OK, 0 rows affected (0.00 sec)
--删除插件的方法 mysql > uninstall plugin rpl_semi_sync_master;
master> show global variables like 'rpl_semi_sync%'; --安装OK后,主上会多几个参数
+------------------------------------+-------+
| Variable_name | Value |
+------------------------------------+-------+
| rpl_semi_sync_master_enabled | OFF | --是否启用master的半同步复制
| rpl_semi_sync_master_timeout | 10000 | --默认主等待从返回信息的超时间时间,10秒。
| rpl_semi_sync_master_trace_level | 32 | --监控
| rpl_semi_sync_master_wait_no_slave | ON | --是否允许每个事物的提交都要等待slave的信号.on为每一个事物都等待
+------------------------------------+-------+
2,在slave上安装插件
slave> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
Query OK, 0 rows affected (0.03 sec)
slave> show global variables like 'rpl_semi_sync%';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled | OFF |
| rpl_semi_sync_slave_trace_level | 32 |
+---------------------------------+-------+
3,master上激活半同步复制
master> set global rpl_semi_sync_master_enabled =on;
Query OK, 0 rows affected (0.00 sec)
4,slave上激活半同步复制
slave> set global rpl_semi_sync_slave_enabled=on;
slave> stop slave IO_THREAD;
slave> start slave IO_THREAD;
5,在master查看状态
master > show global status like 'rpl_semi_sync%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 1 | --有一个从服务器启用半同步复制
| Rpl_semi_sync_master_net_avg_wait_time | 0 | --master等待slave回复的平均等待时间。单位毫秒
| Rpl_semi_sync_master_net_wait_time | 0 | --master总的等待时间。单位毫秒
| Rpl_semi_sync_master_net_waits | 0 | --master等待slave回复的总的等待次数
| Rpl_semi_sync_master_no_times | 0 | --master关闭半同步复制的次数
| Rpl_semi_sync_master_no_tx | 0 | --master 等待超时的次数
| Rpl_semi_sync_master_status | ON | --标记master现在是否是半同步复制状态
| Rpl_semi_sync_master_timefunc_failures | 0 | --master调用时间(如gettimeofday())失败的次数
| Rpl_semi_sync_master_tx_avg_wait_time | 0 | --master花在每个事务上的平均等待时间
| Rpl_semi_sync_master_tx_wait_time | 0 | --master花在事物上总的等待时间
| Rpl_semi_sync_master_tx_waits | 0 | --master事物等待次数
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 | --后来的先到了,而先来的还没有到的次数
| Rpl_semi_sync_master_wait_sessions | 0 | --当前有多少个session因为slave回复而造成等待
| Rpl_semi_sync_master_yes_tx | 0 | --标记slave是否在半同步状态
+--------------------------------------------+-------+
6,在slave上查看状态就只有下面一条信息
slave > show global status like 'rpl_semi_sync%';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON |
+----------------------------+-------+
第三大步
测试:
master > insert into a values (3);
Query OK, 1 row affected (0.01 sec)
master > show global status like 'rpl_semi_sync%_yes_tx';
+-----------------------------+-------+
| Variable_name | Value |
+-----------------------------+-------+
| Rpl_semi_sync_master_yes_tx | 1 | --表示这次事物成功从slave返回一次确认信号
+-----------------------------+-------+
模拟错误,把slave上的mysql停掉
--再回到master上测试
master> insert into a values (4);
Query OK, 1 row affected (10.00 sec) --这次插入一个值需要等待10秒(默认的等待时间)
master> insert into a values (5);
Query OK, 1 row affected (0.01 sec) --现在自动转成了原来的异步模式(类似oracle DG里的最大性能模式)
再次把slave启动,看到半同步复制没启来,是异步模式
重新按下面的步骤把同步模式再启起来就可以了
slave> set global rpl_semi_sync_slave_enabled=on;
slave> stop slave IO_THREAD;
slave> start slave IO_THREAD;
slave启起来后,查看表,发现刚才slave关闭期间的那几条数据还是会自动复制过来,数据又回到一致
=====================================================================
mysql的延时复制(IO线程是实时,只是把SQL线程延时了)
异步或同步复制
A ----------> B
|
|-------> C
延时1天
误删除一张用了好几年的数据表
恢复方法:
1,通过每周的备份来恢复(假设周一0点全备,周三误删除)
先恢复周一的全备到测试库上,然后再恢复全备到现在的二进制日志(除了误删除的那句),再把那张表导出来,导回到生产库上
2,完全通过二进制日志来恢复
需要把这几年内所有的二进制日志先合并,再通过sed,grep,awk等把这张表从建表到现在的所有操作按顺序找出来(当然要除掉你最后误删除的那条),然后应用回去
3,有延时复制的话,在C上导出这张表,导回A
mysql开源管理工具
软件路径在
笔记目录下/mysql/mysql_soft/maatkit-7540.tar.gz
--在mysql AB的slave上安装(只需要在slave上安装,包含下面的步骤都是在slave上做的)
# tar xf maatkit-7540.tar.gz -C /usr/src/
# cd /usr/src/maatkit-7540/
安装方法README文件里有写
# perl Makefile.PL --如果不成功,需要安装perl有关的多个包,可以yum install perl*
# make install
# ls bin/ --这些命令,就是各个管理工具
mk-archiver mk-purge-logs
mk-checksum-filter mk-query-advisor
mk-config-diff mk-query-digest
mk-deadlock-logger mk-query-profiler
mk-duplicate-key-checker mk-show-grants
mk-error-log mk-slave-delay
mk-fifo-split mk-slave-find
mk-find mk-slave-move
mk-heartbeat mk-slave-prefetch
mk-index-usage mk-slave-restart
mk-kill mk-table-checksum
mk-loadavg mk-table-sync
mk-log-player mk-table-usage
mk-merge-mqd-results mk-tcp-model
mk-parallel-dump mk-upgrade
mk-parallel-restore mk-variable-advisor
mk-profile-compact mk-visual-explain
--使用--help查看一个命令的使用方法
# mk-slave-delay --help
mk-slave-delay starts and stops a slave server as needed to make it lag behind
the master. The SLAVE-HOST and MASTER-HOST use DSN syntax, and values are
copied from the SLAVE-HOST to the MASTER-HOST if omitted. For more details,
please use the --help option, or try 'perldoc /usr/bin/mk-slave-delay' for
complete documentation.
--mysql AB(无论同步或异步)正在运行OK的情况下,使用下面的命令在slave上运行;做之间建议把时间同步一下
# mk-slave-delay --defaults-file=/etc/my.cnf --delay=1m --interval=15s --user=root --password=123 --quiet localhost &
--表示延时1分钟,才会应用SQL线程;这里是测试所以才使用很小的时间,实际情况可以调成1小时或2小时
测试:
在master上随便插入几条数据
然后在slave上发现没有马上同步过来
slave > show slave status\G; --查看状态会发现SQL线程状态为NO
Slave_IO_Running: Yes
Slave_SQL_Running: NO
大概等1分钟,就会自动延时同步过来了;
--注意:日志已经传到slave的relay-bin log里了,但由SQL线程延时去解析