复制的基本步骤
- 配置一个服务器作为Master
- 配置一个服务器作为Slave
- 将Slave连接到Master
步骤1和2需要重启MySQL
配置Master
将服务器配置为Master,要确保服务器有一个活动的二进制日志(binary log)和唯一的服务器ID。二进制日志上保存了Master上所有的改变。服务器ID用于区分服务器,要创建二进制日志和服务器ID,需要停掉服务器,然后将log-bin、log-bin-index、server-id选项添加到my.cnf配置文件。
[mysqld]
log-bin=master-bin
log-bin-index=master-bin.index
server-id=1
log-bin选项给出了二进制日志产生的所有文件的基本名(二进制日志包含多个文件)。
log-bin-index给出了二进制索引文件的文件名,这个索引文件保存了所有binlog文件的列表。
严格的说,不需要为log-bin选项提供值,默认值是hostname-bin。hostname的值来自pid-file选项,默认值是主机名。如果管理员后来修改了主机名,binlog文件名也会随之改变,但是索引文件扔可以获取正确的值。最好为服务器创建一个机器无关的唯一的服务器名,因为一系列binlog文件中途改名可能会很乱。
如果没有为log-bin-index赋予任何值,其默认值与binlog文件的基本名相同,索引文件名会随主机名的改变而改变。所以,如果你改变主机名然后重启服务器,将找不到索引文件,从而认为索引文件不存在,导致二进制日志为空。
每个服务器都有一个唯一的服务器ID,所以,如果一个Slave连接了Master,并且其server-id的参数值与master相同,则会产生master与slave服务器id相同的错误。
将log-bin和server-id选项添加到配置文件后重启服务器,然后添加一个复制用户,这样便完成了配置。
在Master上创建一个复制用户
create user repl_user;
grant replication slave on *.* to repl_user identified by 'xxxx';
replication slave 并没有什么特别之处,只是这个用户能够从master上取得二进制日志的转储数据。完全可以给一个常规用户replication slave权限,但是最好还是将复制slave用户与其他用户区别开来。这样的话,以后如果想禁止某些slave的连接,只要删除该用户即可。
配置Slave
需要为每个Slave配置一个唯一的服务器ID,考虑使用relay-log和relay-log-index选项向my.cnf文件添加中继日志文件(relay log file)和中继日志索引文件(relay log index file)的文件名
配置Slave
[mysqld]
server-id = 2
relay-log-index=slave-relay-bin.index
relay-log=slave-relay-bin
和log-bin、log-bin-index选项一样,relay-log和relay-log-index选项默认值取决于hostname。
修改my.cnf后,重启Slave,使配置文件生效
连接Master和Slave
现在创建基本的复制只剩下最后一步了:将Slave指向Master,让他知道从哪里复制。为此需要知道Master的4部分信息:
- 主机名
- 端口号
- Master上拥有Replication Slave权限的用户账号
- 该用户的密码
配置Master时已经创建了一个拥有正确权限的用户账号和密码。主机名由操作系统确定,不能通过my.cnf配置。
启用复制
slave> CHANGE MASTER TO
-> MASTER_HOST = 'master-1',
-> MASTER_PORT = 3306,
-> MASTER_USER='repl_user',
-> MASTER_PASSWORD = 'XXXX'
slave> START SLAVE;
以上,已经建立了Master和Slave之间的第一个复制。如果在Master数据库表上做一些改动,如创建新表并填充数据,将发现这些改变都会复制到Slave。
MASTER_HOST的参数值可以是主机名或者IP地址。
二进制日志简介
复制过程需要二进制日志 (binlog),他记录了服务器数据库上的所有改变。语句执行结束时,将在二进制日志的末尾写入一条记录,同时通知语句解析器语句已经执行完毕。通常只有即将执行完毕的语句才会被写入二进制日志。
二进制日志记录了什么
二进制日志的目的是记录数据库中表的更改,然后用于复制和PITR,少数审计情况也会用到。
注意二进制日志只记录包括数据库的改动,哪些不改变数据的语句不会写入二进制日志。
传统意义上说,MySQL复制记录了产生变化的SQL语句,称为基于语句的复制(statement-based replicaton)。基于语句的复制的缺点是无法保证所有语句都正确复制。5.1版本中,MySQL还提供了基于行的复制(row-based replication)。相比于基于语句的复制,基于行的复制将每一次改动记为二进制日志中的一行。基于行的复制不仅更加方便,而且有时速度更快。
考虑一个含有多表连接或WHERE条件的复杂更新,看看这两种复制有何不同。真正需要知道的是更新后每行的状态,而不是像基于语句的复制那样把所有的逻辑都记录在Slave上重新执行。相反,如果某个更新改变了10000行,你可能宁愿只记录这条语句,而不是像基于行的复制那样记录10000个单独的改动。
观察复制的动作
使用命令行客户端连接Master,然后执行一些命令获取二进制日志:
create table tb1(text TEXT);
insert into tb1 values("year!replication");
select * from tb1;
flush logs;
flush logs强制轮换二进制日志,从而得到一个完整的 二进制文件。使用show binlog events命令进一步查看该文件
show binlog events\G;
...........................1.row.....................................
log_name:master-bin.00001
pos:4
event_type:format_desc
server_id:1
end_log_pos:106
info: server ver:5.1.33,binlog ver 4
...........................2.row.....................................
log_name:master-bin.00001
pos:106
event_type:query
server_id:1
end_log_pos:197
info: use 'test';create table tb1(text TEXT)
...........................3.row.....................................
log_name:master-bin.00001
pos:197
event_type:query
server_id:1
end_log_pos:305
info: use 'test';insert into tb1 values("year!replication")
...........................4.row.....................................
log_name:master-bin.00001
pos:305
event_type:rotate
server_id:1
end_log_pos:349
info: master-bin.00002;pos=4