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线程延时去解析