Mysql内建的复制功能是构建大型,高性能应用程序的基础。
将Mysql的数据分布到多个系统上去,这种分布的机制,是经过将Mysql的某一台主机的数据复制到其它主机(slaves)上,并从新执行一遍来实现的。mysql
复制过程当中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器。主服务器将更新写入二进制日志文件,并维护文件的一个索引以跟踪日志循环。这些日志能够记录发送到从服务器的更新。当一个从服务器链接主服务器时,它通知主服务器从服务器在日志中读取的最后一次成功更新的位置。从服务器接收从那时起发生的任何更新,而后封锁并等待主服务器通知新的更新。算法
请注意当你进行复制时,全部对复制中的表的更新必须在主服务器上进行。不然,你必需要当心,以免用户对主服务器上的表进行的更新与对从服务器上的表所进行的更新之间的冲突。sql
(1):基于语句的复制(逻辑复制):在主服务器上执行的SQL语句,在从服务器上执行一样的语句。
MySQL默认采用基于语句的复制,效率比较高。
一旦发现无法精确复制时,会自动选着基于行的复制。
(2):基于行的复制:把改变的内容复制过去,而不是把命令在从服务器上执行一遍. 从mysql5.1开始支持
(3):混合类型的复制: 默认采用基于语句的复制,一旦发现基于语句的没法精确的复制时,就会采用基于行的复制。数据库
1.2 . 复制解决的问题缓存
MySQL复制技术有如下一些特色:
(1) 数据分布 (Data distribution )
(2) 负载平衡(load balancing)
(3) 备份(Backups)
(4) 高可用性和容错行 High availability and failover 服务器
总体上来讲,复制有3个步骤: 异步
(1) master将改变记录到二进制日志(binary log)中
(这些记录叫作二进制日志事件,binary log events);
(2) slave将master的binary log events拷贝到它的中继日志(relay log);性能
(3) slave重作中继日志中的事件,将改变反映它本身的数据。
测试
下图描述了复制的过程:spa
该过程的第一部分:
在主库上记录二进制日志。在每次准备提交事务完成数据更新前,主库将数据更新的事件记录到二进制日志中。
MySQL将按事务提交的顺序而非每条语句的执行顺序来记录二进制日志,即便事务中的语句都是交叉执行的。
在事件写入二进制日志完成后,主库通知存储引擎提交事务。
第二步:
备库将主库的binary log拷贝到它本地本身的中继日志。
首先,备库开始一个工做线程——I/O线程。I/O线程与主库创建一个普通的链接,
而后在主库启动一个特殊的二进制转储线程 binlog dump process。
Binlog dump process从主库的二进制日志中读取事件,若是该线程已经跟上主库,它会睡眠并等待主库产生新的事件。
备库I/O线程会将接收到事件写入中继日志。
第三步:
备库的 SQL slave thread(SQL从线程)处理该过程的最后一步。
SQL线程从中继日志读取事件,并重放其中的事件而更新备库的数据,使其与主库中的数据一致。
只要该线程与I/O线程保持一致,中继日志一般会位于OS的缓存中,因此中继日志的开销很小。
此外,在master中也有一个工做线程:和其它MySQL的链接同样,slave在master中打开一个链接也会使得master开始一个线程。复制过程有一个很重要的限制——复制在slave上是串行化的,也就是说master上的并行更新操做不能在slave上并行操做。
有两台MySQL数据库服务器Master和slave,Master为主服务器,slave为从服务器,初始状态时,Master和slave中的数据信息相同,当Master中的数据发生变化时,slave也跟着发生相应的变化,使得master和slave的数据信息同步,达到备份的目的。
要点:
负责在主、从服务器传输各类修改动做的媒介是主服务器的二进制变动日志,这个日志记载着须要传输给从服务器的各类修改动做。
所以:
主服务器必须激活二进制日志功能。
从服务器必须具有足以让它链接主服务器并请求主服务器把二进制变动日志传输给它的权限。
准备工做:
1.在每台服务器上建立 复制帐号
2.配置主库和备库
3.通知备库链接到主库,并从主库复制数据
一、在主数据库中创建一个备份账户:从库的I/O线程 使用该备份帐户 链接到主库。
进行复制操做的备份帐户会授予REPLICATION SLAVE权限。
用户名的密码都会存储在文本文件master.info中
创建一个账户backup,而且只能容许从10.0.0.xxx这个地址上来登录,密码是1234。
(若是由于mysql版本新旧密码算法不一样,能够设置:set password for 'backup'@'10.100.0.200'=old_password('1234'))
在从库一样创建相同帐户;
命令以下:
mysql>GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.*
->TO backup@'10.0.0.%' IDENTIFIED BY '1234';
注意:备份帐户事实上只须要有主库的 REPLICATION SALVE 权限,
并不必定须要每一端服务器都有REPLICATION CLIENT权限。
replication slave:拥有此权限能够 查看从服务器,从主服务器读取二进制日志。
replication client:拥有此权限能够 查询master server、slave server状态。
为何要在主从两个库 创建相同权限的用户呢?
未来有须要时 方便主从两库交换角色
2.2 配置主库
接下来对master进行配置,包括打开二进制日志,指定惟一的servr ID。
在配置文件加入以下值:
server-id=8
log-bin=mysql-bin
#server-id:为主库服务器的ID值,默认为1,这个值不能与其余服务器冲突;一般采用IP地址末位,
#log-bin:二进制变动日值
重启master;
运行SHOW MASTER STATUS,输出以下:
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 120 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
2.3 配置从库
server_id = 9
log_bin = mysql-bin
relay_log = /var/lib/mysql/mysql-relay-bin
log_slave_updates = 1
read_only
server_id:是必须的,不能重复
log_bin: 二进制日志并不必定要开启,可是在一些状况下,必须设置,
例如,若是slave为其它slave的master,必须设置bin_log
relay_log: 配置中继日志位置和名字
log_slave_updates: 表示slave将复制事件写进本身的二进制日志(后面会看到它的用处)。
会增长一些备库的负载
注意:开启了slave的二进制日志,却没有开启log_slave_updates,这可能会出现一些问题,
例如slave的数据被改变。
因此,尽可能使用read_only,它防止改变数据(除了特殊的线程)。
可是,read_only并是很实用,特别是那些须要在slave上建立表的应用。
注意:不要在my.cnf 中设置 master_port或 master_host 这是老的配置方式,已经被废弃。
mysql> CHANGE MASTER TO MASTER_HOST='10.0.0.42',
-> MASTER_USER='backup',
-> MASTER_PASSWORD='1234',
-> MASTER_LOG_FILE='mysql-bin.000001',
-> MASTER_LOG_POS=0;
能够用SHOW SLAVE STATUS语句查看slave的设置是否正确:
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: server1
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 4
Relay_Log_File: mysql-relay-bin.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: No
Slave_SQL_Running: No
...omitted...
Seconds_Behind_Master: NULL
Slave_IO_State, Slave_IO_Running, 和Slave_SQL_Running是No
代表slave尚未开始复制过程。日志的位置为4而不是0,这是由于0只是日志文件的开始位置,并非日志位置。
实际上,MySQL知道的第一个事件的位置是4。
开始复制,你能够运行:
mysql> START SLAVE;
Query OK, 0 rows affected (0.01 sec)
从库运行SHOW SLAVE STATUS查看输出结果:
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: server1
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 164
Relay_Log_File: mysql-relay-bin.000001
Relay_Log_Pos: 164
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
...omitted...
Seconds_Behind_Master: 0
行2 为I/O线程,行3为SQL线程;
以上的全部操做都是基于两台新建立的数据库服务器,也就是所两台数据库数据相同。
这不是典型的案列,多数状况下是有一个已经运行一段时间的数据库,而后用一个新安装的数据库和它进行同步,
此时新库尚未数据,