MySQL 优化4--Master/Slave实现读写分离

[本文摘自 http://linuxme.blog.51cto.com/1850814/383742/ 和  http://hi.baidu.com/lxylxy888666/item/21319114d69fb93db9318099]

1.Master/Slave 的工作原理图

MySQL 优化4--Master/Slave实现读写分离_第1张图片

2.工作过程
    MySQL的复制(replication)是一个异步的复制,从一个MySQL instace(称之为Master)复制到另一个MySQL instance(称之Slave)。实现整个复制操作主要由三个进程完成的,其中两个进程在Slave(Sql进程和IO进程),另外一个进程在 Master(IO进程)上。
    要实施复制,首先必须打开Master端的binary log(bin-log)功能,否则无法实现。因为整个复制过程实际上就是Slave从Master端获取该日志然后再在自己身上完全顺序的执行日志中所记录的各种操作。
    
    复制的基本过程如下:
(1)Slave上面的IO进程连接上Master,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容;
(2)Master接收到来自Slave的IO进程的请求后,通过负责复制的IO进程根据请求信息读取制定日志指定位置之后的日志信息,返回给Slave 的IO进程。返回信息中除了日志所包含的信息之外,还包括本次返回的信息已经到Master端的bin-log文件的名称以及bin-log的位置;
(3)Slave的IO进程接收到信息后,将接收到的日志内容依次添加到Slave端的relay-log文件的最末端,并将读取到的Master端的 bin-log的文件名和位置记录到master-info文件中,以便在下一次读取的时候能够清楚的高速Master“我需要从某个bin-log的哪个位置开始往后的日志内容,请发给我”;
(4)Slave的Sql进程检测到relay-log中新增加了内容后,会马上解析relay-log的内容成为在Master端真实执行时候的那些可执行的内容,并在自身执行。

3.设置MySQL主从配置的优点
(1)解决web应用系统,数据库出现的性能瓶颈,采用数据库集群的方式来实现查询负载;一个系统中数据库的查询操作比更新操作要多得多,通过多台查询服务器将 数据库的查询分担到不同的查询服务器上从而提高查询效率,即分布式;
(2)MySQL数据库支持数据库的主从复制功能,使用主数据库进行数据的插入、删除与更新操作,而从数据库则专门用来进行数据查询操作,这样可以将更新操作和查询操作分担到不同的数据库上,从而提高了查询效率,即读写分离。

4.两个重要的选项
(1)--logs-slave-updates
    这个是在my.cnf文件配置的
    通常情况,从服务器从主服务器接收到的更新不记入它的二进制日志。该选项告诉从服务器将其SQL线程执行的更新记入到从服务器自己的二进制日志。为了使该 选项生效,还必须用--logs-bin选项启动从服务器以启用二进制日志。如果想要应用链式复制服务器,应使用--logs-slave- updates。例如,可能你想要这样设置:
    A -> B -> C
    也就是说,A为从服务器B的主服务器,B为从服务器C的主服务器。为了能工作,B必须既为主服务器又为从服务器。你必须用--logs-bin启动A和B以启用二进制日志,并且用--logs-slave-updates选项启动B。

(2)--slave-skip-errors=[err_code1,err_code2,... | all]
    这个是在mysql启动时的选项
    通常情况,当出现错误时复制停止,这样给你一个机会手动解决数据中的不一致性问题。该选项告诉从服务器SQL线程当语句返回任何选项值中所列的错误时继续复制。
    如果你不能完全理解为什么发生错误,则不要使用该选项。如果复制设置和客户程序中没有bug,并且MySQL自身也没有bug,应不会发生停止复制的错误。滥用该选项会使从服务器与主服务器不能保存同步,并且你找不到原因。
    对于错误代码,你应使用从服务器错误日志中错误消息提供的编号和SHOW SLAVE STATUS的输出。服务器错误代码列于附录B:错误代码和消息。
    你也可以(但不应)使用不推荐的all值忽略所有错误消息,不考虑所发生的错误。无需而言,如果使用该值,我们不能保证数据的完整性。在这种情况下,如果从服务器的数据与主服务器上的不相近请不要抱怨(或编写bug报告)。已经警告你了。
    例如:
    以下是代码片段:

--slave-skip-errors=1062,1053
--slave-skip-errors=all

5.重要的问题 
(1)如果主服务器正在运行并且不想停止主服务器,怎样配置一个从服务器?
    有多种方法。如果你在某时间点做过主服务器备份并且记录了相应快照的二进制日志名和偏移量(通过SHOW MASTER STATUS命令的输出),采用下面的步骤:
以下是引用片段:
①确保从服务器分配了一个唯一的服务器ID号。
②在从服务器上执行下面的语句,为每个选项填入适当的值:
mysql> CHANGE MASTER TO
->     MASTER_HOST='master_host_name',
->     MASTER_USER='master_user_name',
->     MASTER_PASSWORD='master_pass',
->     MASTER_LOG_FILE='recorded_log_file_name',
->     MASTER_LOG_POS=recorded_log_position;
在从服务器上执行START SLAVE语句。            
   
    如果你没有备份主服务器,这里是一个创建备份的快速程序。所有步骤都应该在主服务器主机上执行。以下是引用片段:
①发出该语句:
mysql> FLUSH TABLES WITH READ LOCK;
仍然加锁时,执行该命令(或它的变体):
shell> tar zcf /tmp/backup.tar.gz /var/lib/mysql
发出该语句并且确保记录了以后用到的输出:
mysql>SHOW MASTER STATUS;
释放锁:
mysql> UNLOCK TABLES;
    一个可选择的方法是,转储主服务器的SQL来代替前面步骤中的二进制复制。要这样做,你可以在主服务器上使用mysqldump --master-data,以后装载SQL转储到到你的从服务器。然而,这比进行二进制复制速度慢。
     不管你使用这两种方法中的那一个,当你有一个快照和记录了日志名与偏移量时,后来根据说明操作。你可以使用相同的快照建立多个从服务器。一旦你拥有主服务 器的一个快照,可以等待创建一个从服务器,只要主服务器的二进制日志完整。两个能够等待的时间实际的限制是指在主服务器上保存二进制日志的可用硬盘空间和 从服务器同步所用的时间。
    你也可以使用LOAD DATA FROM  MASTER。这是一个方便的语句,它传输一个快照到从服务器并且立即调整日志名和偏移量。将来,LOAD DATA FROM  MASTER将成为创建从服务器的推荐方法。然而需要注意,它只工作在MyISAM  表上并且可能长时间持有读锁定。它并不象我们希望的那样高效率地执行。如果你有大表,执行FLUSH TABLES WITH READ  LOCK语句后,这时首选方法仍然是在主服务器上制作二进制快照。

(2)从服务器需要始终连接到主服务器吗?
    不,不需要。从服务器可以宕机或断开连接几个小时甚至几天,重新连接后获得更新信息。例如,你可以在通过拨号的链接上设置主服务器/从服务器关系,其 中只是偶尔短时间内进行连接。这意味着,在任何给定时间,从服务器不能保证与主服务器同步除非你执行某些特殊的方法。将来,我们将使用选项来阻塞主服务器直到有一个从服务器同步。
    当备份从服务器的数据时,你还应备份这两个小文件以及中继日志文件。它们用来在恢复从服务器的数据后继续进行复制。如果丢失了中继日志但仍然有 relay-log.info文件,你可以通过检查该文件来确定SQL线程已经执行的主服务器中二进制日志的程度。然后可以用 Master_Log_File和Master_LOG_POS选项执行CHANGE MASTER  TO来告诉从服务器重新从该点读取二进制日志。当然,要求二进制日志仍然在主服务器上。
    如果从服务器正复制LOAD DATA  INFILE语句,你应也备份该目录内从服务器用于该目的的任何SQL_LOAD-*文件。从服务器需要这些文件继续复制任何中断的LOAD DATA  INFILE操作。用--slave-load-tmpdir选项来指定目录的位置。如果未指定, 默认值为tmpdir变量的值。

(3)遇到这样的错误如:“Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'Could not find first log file name in binary log index file'”等或由于清数据导致主从库不同步了,解决办法如下: 
①先进入slave中执行:"slave stop;"来停止从库同步; 
再去master中执行:"flush logs;"来清空日志; 
然后在master中执行:"show master status;"查看下主库的状态,主要是日志的文件和position; 
然后回到slave中,执行:"CHANGE MASTER TO MASTER_LOG_FILE='log-bin.000004',MASTER_LOG_POS=106;",文件和位置对应master中的; 
最后在slave中执行:"slave start;"来启动同步。

你可能感兴趣的:(mysql,原理,读写分离,master/slave)