mysql编译安装AB复制

1、复制进程复制

Mysql复制(replication)是一个异步的复制,从一个Mysql instace(称之为Master)复制到另一个Mysql instance(称之Slave)。实现整个复制操作主要由三个进程完成的,其中两个进程在SlaveSql进程和IO进程),另外一个进程在 MasterIO进程)上。

要实施复制,首先必须打开Master端的binary logbin-log)功能,否则无法实现。因为整个MySQL 复制过程实际上就是SlaveMaster端获取该日志然后再在自己身上完全顺序的执行日志中所记录的各种操作。

复制的基本过程如下:

1)Slave上面的IO进程连接上Master,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容;

2)Master接收到来自SlaveIO进程的请求后,通过负责复制的IO进程根据请求信息读取制定日志指定位置之后的日志信息,返回给Slave IO进程。返回信息中除了日志所包含的信息之外,还包括本次返回的信息已经到Master端的bin-log文件的名称以及bin-log的位置;

3)SlaveIO进程接收到信息后,将接收到的日志内容依次添加到Slave端的relay-log文件的最末端,并将读取到的Master端的 bin-log的文件名和位置记录到master-info文件中,以便在下一次读取的时候能够清楚的高速Master“我需要从某个bin-log的哪 个位置开始往后的日志内容,请发给我

4)SlaveSql进程检测到relay-log中新增加了内容后,会马上解析relay-log的内容成为在Master端真实执行时候的那些可执行的内容,并在自身执行。

实际上在老版本的Mysql的复制实现在Slave端并不是两个进程完成的,而是由一个进程完成。但是后来发现这样做存在较大的风险和性能问题,主要如下:

首先,一个进程就使复制bin-log日志和解析日志并在自身执行的过程成为一个串行的过程,性能受到了一定的限制,异步复制的延迟也会比较长。

另外,Slave端从Master端获取bin-log过来之后,需要接着解析日志内容,然后在自身执行。在这个过程中,Master端可能又产生了大量 变化并声称了大量的日志。如果在这个阶段Master端的存储出现了无法修复的错误,那么在这个阶段所产生的所有变更都将永远无法找回。如果在Slave 端的压力比较大的时候,这个过程的时间可能会比较长。

所以,后面版本的Mysql为了解决这个风险并提高复制的性能,将Slave端的复制改为两个进程来完成。提出这个改进方案的人是Yahoo!的一位工程 “Jeremy Zawodny”。这样既解决了性能问题,又缩短了异步的延时时间,同时也减少了可能存在的数据丢失量。

当然,即使是换成了现在这样两个线程处理以后,同 样也还是存在slave数据延时以及数据丢失的可能性的,毕竟这个复制是异步的。只要数据的更改不是在一个事物中,这些问题都是会存在的。如果要完全避免 这些问题,就只能用mysqlcluster来解决了。

不过mysqlcluster是内存数据库的解决方案,需要将所有数据都load到内存中,这 样就对内存的要求就非常大了,对于一般的应用来说可实施性不是太大。

2、复制实现级别

Mysql的复制可以是基于一条语句(Statement level),也可以是基于一条记录(Row level),可以在Mysql的配置参数中设定这个MySQL 复制级别,不同复制级别的设置会影响到Master端的bin-log记录成不同的形式。

Row Level:日志中会记录成每一行数据被修改的形式,然后在slave端再对相同的数据进行修改。

优点:在row level模式下,bin-log中可以不记录执行的sql语句的上下文相关的信息,仅仅只需要记录那一条记录被修改了,修改成什么样了。所以row level的日志内容会非常清楚的记录下每一行数据修改的细节,非常容易理解。而且不会出现某些特定情况下的存储过程,或function,以及 trigger的调用和触发无法被正确复制的问题。

缺点:row level下,所有的执行的语句当记录到日志中的时候,都将以每行记录的修改来记录,这样可能会产生大量的日志内容,比如有这样一条update 句:

update product set owner_member_id = ‘b’ where owner_member_id = ‘a’,执行之后,日志中记录的不是这条update语句所对应额事件(mysql以事件的形式来记录bin-log日志),而是这条语句所更新的每一条 记录的变化情况,这样就记录成很多条记录被更新的很多个事件。

自然,bin-log日志的量就会很大。尤其是当执行alter table之类的语句的时候,产生的日志量是惊人的。因为Mysql对于alter table之类的表结构变更语句的处理方式是整个表的每一条记录都需要变动,实际上就是重建了整个表。那么该表的每一条记录都会被记录到日志中。

Statement Level:每一条会修改数据的sql都会记录到 masterbin-log中。slave在复制的时候sql进程会解析成和原来master端执行过的相同的sql来再次执行。

优点:statement level下的优点首先就是解决了row level下的缺点,不需要记录每一行数据的变化,减少bin-log日志量,节约IO,提高性能。因为他只需要记录在Master上所执行的语句的细节,以及执行语句时候的上下文的信息。

缺点:由于他是记录的执行语句,所以,为了让这些语句在slave端也能正确执行,那么他还必须记录每条语句在执行的时候的一些相关信息,也就是上下文信 息,以保证所有语句在slave端杯执行的时候能够得到和在master端执行时候相同的结果。

另外就是,由于Mysql现在发展比较快,很多的新功能不 断的加入,使mysql复制遇到了不小的挑战,自然复制的时候涉及到越复杂的内容,bug也就越容易出现。在statement level下,目前已经发现的就有不少情况会造成mysql的复制出现问题,主要是修改数据的时候使用了某些特定的函数或者功能的时候会出现,

如:sleep()函数在有些版本中就不能真确复制,在存储过程中使用了last_insert_id()函数,可能会使slavemaster上得到 不一致的id等等。由于row level是基于每一行来记录的变化,所以不会出现类似的问题。

从官方文档中看到,之前的Mysql一直都只有基于statement的复制模式,直到5.1.5版本的Mysql才开始支持row level的复制。从5.0开始,Mysql的复制已经解决了大量老版本中出现的无法正确复制的问题。但是由于存储过程的出现,给Mysql的复制又带来 了更大的新挑战。

另外,看到官方文档说,从5.1.8版本开始,Mysql提供了除Statement LevelRow Level之外的第三种复制模式:Mixed,实际上就是前两种模式的结合。在Mixed模式下,Mysql会根据执行的每一条具体的sql语句来区分对 待记录的日志形式,也就是在StatementRow之间选择一种。新版本中的Statment level还是和以前一样,仅仅记录执行的语句。

而新版本的Mysql中队row level模式也被做了优化,并不是所有的修改都会以row level来记录,像遇到表结构变更的时候就会以statement模式来记录,如果sql语句确实就是update或者delete等修改数据的语句, 那么还是会记录所有行的变更。

3、复制常用架构

Mysql复制环境90%以上都是一个Master带一个或者多个Slave的架构模式,主要用于读压力比较大的应用的数据库端廉价扩展解决方案。因为只 masterslave的压力不是太大(尤其是slave端压力)的话,异步复制的延时一般都很少很少。尤其是自slave端的复制方式改成两个进程 处理之后,更是减小了slave端的延时。

而带来的效益是,对于数据实时性要求不是特别的敏感度的应用,只需要通过廉价的pc server来扩展slave的数量,将读压力分散到多台slave的机器上面,即可解决数据库端的读压力瓶颈。这在很大程度上解决了目前很多中小型网站 的数据库压力瓶颈问题,甚至有些大型网站也在使用类似方案解决数据库瓶颈。

一个Master带多个slave的架构实施非常简单,多个slave和单个slave的实施并没有太大区别。在Master端并不care有多少个 slave连上了master端,只要有slave进程通过了连接认证,向他请求binlog信息,他就会按照连接上来的io进程的要求,读取自己的 binlog信息,返回给slaveIO进程。对于slave的配置细节,在Mysql的官方文档上面已经说的很清楚了,甚至介绍了多种实现slave 的配置方法。

Mysql不支持一个Slave instance从属于多个Master的架构。就是说,一个slave instance只能接受一个master的同步源,听说有patch可以改进这样的功能,但没有实践过。Mysql AB之所以不实现这样的功能,主要是考虑到冲突解决的问题。

Mysql也可以搭建成dual master模式,也就是说两个Mysql instance互为对方的Master,也同时为对方的Slave。不过一般这种架构也是只有一端提供服务,避免冲突问题。因为即使在两边执行的修改有 先后顺序,由于MySQL 复制的异步实现机制,同样会导致即使在晚做的修改也可能会被早做的修改所覆盖,就像如下情形:

时间点 Mysql A Mysql B

1 更新xy记录为10

2 更新xy记录为20

3 获取到A日志并应用,更新x表的y记录为10(不符合期望)

4 获取B日志更新xy记录为20(符合期望)

这样,不仅在B库上面的数据不是用户所期望的结果,AB两边的数据也出现了不一致的情况。除非能将写操作根据某种条件固定分开在AB两端,保证不会交叉写入,才能够避免上面的问题。

 

 

 

mysql主从复制

主服务器IP192.168.99.10

从服务器IP192.168.99.20

()安装mysql(主从服务器操作相同)

yum -y install gcc gcc-c++ ncurses-devel

增加组和用户

#/usr/sbin/groupadd mysql       

#/usr/sbin/useradd -g mysql mysql -s /sbin/nologin

解压、编译、安装

#tar xvf mysql-5.1.35.tar.gz

#cd mysql-5.1.35

#./configure --prefix=/usr/local/mysql --localstatedir=/data/mysql/data --with-extra-charsets=utf8,gb2312,gbk --with-pthread --enable-thread-safe-client

 

mysql编译参数说明:根据 ./configure --help 查看支持配置的参数

 

-pgcc和-O6编译
CFLAGS="-O6 -mpentiumpro -fomit-frame-pointer" CXX=gcc CXXFLAGS="-O6 -mpentiumpro -fomit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti"
总体性能可提高10%,当然如果服务器不是用奔腾处理器,就不必用它了,因为它是专为奔腾系统设计的

 

-static静态编译
--enable-static
--with-client-ldflags=-all-static
--with-mysqld-ldflags=-all-static
以静态方式编译客户端和服务端,能提高13%性能

 

--enable-thread-safe-client
以线程方式编译客户端

 

--without-innodb
去掉innodb表支持,innodb是一种支持事务处理的表,适合企业级应用

 

--without-isam
去掉isam表类型支持,现在很少用了,isam表是一种依赖平台的表

 

--without-ndb-debug
取消导航调试

 

--localstatedir=/usr/local/mysql/var/
日志文件目录

 

--with-server-suffix=-enterprise-gpl
给MySQL加个后缀名,在用mysql登录的时候在版本号的后面可以看到

 

--without-debug
去除诊断模式,如果用--with-debug=full编译,大多数查询慢20%

 

--with-big-tables
大表支持

 

--with-extra-charsers=gbk,gb2312,utf8
设置支持gbk,gb2312,utf8字符集

 

--with-pthread
强制使用pthread库(posix线程库)

 

--enable-assembler
使用一些字符函数来汇编版本

 

--with-federated-storage-engine
这个参数已经被废除,代替它的是--with-plugin系列

 

cp support-files/my-medium.cnf /usr/local/mysql/my.cnf
mysql/support-files里面有配置文件范本,根据实际情况选择或者更改

 

/usr/local/mysql/bin/mysql_install_db --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data --user=mysql --defaults-file=/usr/local/mysql/my.cnf --pid-file=/usr/local/mysql/mysql.pid
设定默认值:默认空间路径;默认数据文件路径;默认用户;默认配置文件路径;默认PID文件路径。

本脚步未加入的编译参数:

 

--with-charset=utf8
设置默认字符集

 

--with-unix-socket-path=/usr/local/mysql/tmp/mysql.sock
使用unix套接字链接提高7.5%性能,所以在windows下mysql性能肯定不如 unix

 

--with-tcp-port=3306
指定MySQL实例将监听TCP 3306端口

 

 

#make && make install

拷贝配置文件

#cp support-files/my-large.cnf   /etc/my.cnf

修改权限

#chown -R mysql.mysql /usr/local/mysql

初始化数据库

#/usr/local/mysql/bin/mysql_install_db --user=mysql

改变权限

#chown -R mysql:mysql /data/mysql/data

()修改配置文件

主服务器

server-id = 1

从服务器

server-id = 2..3..4依次增加

()启动服务(主从相同)

#/usr/local/mysql/bin/mysqld_safe --user=mysql&

()授权(仅主服务器)

mysql>GRANT REPLICATION SLAVE ON *.* to 'rep'@'192.168.99.%' identified by 'sasasa';

()查询主数据库状态(主服务器上)

mysql> show master status;

+------------------+----------+--------------+------------------+

| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |

+------------------+----------+--------------+------------------+

| mysql-bin.000003 |      771 |              |                  |

+------------------+----------+--------------+------------------+

记住fileposition的值

()配置从服务器

mysql> change master to master_host='192.168.99.10', master_user='rep', master_password='sasasa1', master_log_file='mysql-bin.000003', master_log_pos=771;

master_host主服务器ipmaster_user连接帐户,master_password连接密码,maser_log_file填入上面的file值,master_log_pos填入上面的position

mysql> start slave;        启用了复制功能

mysql> show slave status/G;        检查slave状态

*************************** 1. row ***************************

               Slave_IO_State: Waiting for master to send event

                  Master_Host: 192.168.99.10

                  Master_User: rep

                  Master_Port: 3306

                Connect_Retry: 60

              Master_Log_File: mysql-bin.000003

          Read_Master_Log_Pos: 771

               Relay_Log_File: localhost-relay-bin.000002

                Relay_Log_Pos: 251

        Relay_Master_Log_File: mysql-bin.000003

             Slave_IO_Running: Yes

            Slave_SQL_Running: Yes

              Replicate_Do_DB:

          Replicate_Ignore_DB:

           Replicate_Do_Table:

       Replicate_Ignore_Table:

      Replicate_Wild_Do_Table:

Replicate_Wild_Ignore_Table:

                   Last_Errno: 0

                   Last_Error:

                 Skip_Counter: 0

          Exec_Master_Log_Pos: 771

              Relay_Log_Space: 410

              Until_Condition: None

               Until_Log_File:

                Until_Log_Pos: 0

           Master_SSL_Allowed: No

           Master_SSL_CA_File:

           Master_SSL_CA_Path:

              Master_SSL_Cert:

            Master_SSL_Cipher:

               Master_SSL_Key:

        Seconds_Behind_Master: 0

Master_SSL_Verify_Server_Cert: No

                Last_IO_Errno: 0

                Last_IO_Error:

               Last_SQL_Errno: 0

               Last_SQL_Error:

 

注意:Slave_IO_Running: Yes Slave_SQL_Running: Yes 如果这两个状态不是yes,那么请检查上面的配置是否正确,主要是fileposition设置是否正确,从库是否能用主库的账号登陆

如果主服务器还有数据传输,那么先进行锁表操作 mysql> FLUSH TABLES WITH READ LOCK; 然后按照第五步的进行操作

 

 

 

关于Slave_IO_Running:No
2010-08-05 15:55

mysql replication 中slave机器上有两个关键的进程,死一个都不行,一个是slave_sql_running,一个是Slave_IO_Running,一个负责与主机的io通信,一个负责自己的slave mysql进程。下面写一下,这两个要是有no了,怎么恢复。。

如果是slave_io_running no了,那么就我个人看有三种情况,一个是网络有问题,连接不上,像有一次我用虚拟机搭建replication,使用了nat的网络结构,就是死都连不上,第二个是有可能my.cnf有问题,配置文件怎么写就不说了,网上太多了,最后一个是授权的问题,replication slave和file权限是必须的。如果不怕死就all咯。。

一旦io为no了先看err日志,看看爆什么错,很可能是网络,也有可能是包太大收不了,这个时候主备上改max_allowed_packet这个参数。

如果是slave_sql_running no了,那么也有两种可能,一种是slave机器上这个表中出现了其他的写操作,就是程序写了,这个是会有问题的,今天我想重现,但是有时候会有问题,有时候就没有问题,现在还不是太明了,后面再更新,还有一种占绝大多数可能的是slave进程重启,事务回滚造成的,这也是mysql的一种自我保护的措施,像关键时候只读一样。

这个时候想恢复的话,只要停掉slave,set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;再开一下slave就可以了,这个全局变量赋值为N的意思是:

This statement skips the next N events from the master. This is useful for recovering from replication stops caused by a statement.

This statement is valid only when the slave thread is not running. Otherwise, it produces an error.

呵呵,讲的比我清楚。


 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值