MySQL复制的概述、安装、故障、技巧、工具(火丁分享)

 更新时间:2011年04月06日 16:22:15   作者:  
首先主服务器把数据变化记录到主日志,然后从服务器通过I/O线程读取主服务器上的主日志,并且把它写入到从服务器的中继日志中,接着SQL线程读取中继日志,并且在从服务器上重放,从而实现MySQL复制。
同MongoDB,Redis这样的NoSQL数据库的复制相比,MySQL复制显得相当复杂!

概述

首先主服务器把数据变化记录到主日志,然后从服务器通过I/O线程读取主服务器上的主日志,并且把它写入到从服务器的中继日志中,接着SQL线程读取中继日志,并且在从服务器上重放,从而实现MySQL复制。具体如下图所示:

整个过程反映到从服务器上,对应三套日志信息,可在从服务器上用如下命令查看:
复制代码 代码如下:

mysql> SHOW SLAVE STATUS;


Master_Log_File & Read_Master_Log_Pos:下一个传输的主日志信息。
Relay_Master_Log_File & Exec_Master_Log_Pos:下一个执行的主日志信息。
Relay_Log_File & Relay_Log_Pos:下一个执行的中继日志信息。
理解这些日志信息的含义对于解决故障至关重要,后文会详细阐述。
安装
先在主服务器上创建复制账号:
复制代码 代码如下:

mysql> GRANT REPLICATION SLAVE ON *.*
TO '<SLAVE_USER>'@'<SLAVE_HOST>'
IDENTIFIED BY '<SLAVE_PASSWORD>';

注:出于安全性和灵活性的考虑,不要把root等具有SUPER权限用户作为复制账号。然后设置主服务器配置文件(缺省:/etc/my.cnf):
复制代码 代码如下:

[mysqld]

server_id = 100
log_bin = mysql-bin
log_bin_index = mysql-bin.index
sync_binlog = 1
innodb_flush_log_at_trx_commit = 1
innodb_support_xa = 1

注:一定要保证主从服务器各自的server_id唯一,避免冲突。

注:如果没有指定log_bin的话,缺省会使用主机名作为名字,如此一来一旦主机名发生改变,就会出问题,所以推荐指定log_bin(从服务器的relay_log存在一样的问题)。

注:sync_binloginnodb_flush_log_at_trx_commitinnodb_support_xa三个选项都是出于安全目的设置的,不是复制的必须选项。

接着设置从服务器配置文件(缺省:/etc/my.cnf):

复制代码 代码如下:

[mysqld]
server_id = 200
log_bin = mysql-bin
log_bin_index = mysql-bin.index
relay_log = mysql-relay-bin
relay_log_index = mysql-relay-bin.index
read_only = 1
skip_slave_start = 1
log_slave_updates = 1

注:如果用户有SUPER权限,则read_only无效。

注:有了skip_slave_start,除非使用START SLAVE命令,否则从服务器不会开始复制。

注:设置log_slave_updates,让从服务器记录日志,有助于在必要时把从切换成主。

下面最重要的步骤是如何克隆一份主服务器的数据:

如果数据库使用的是MyISAM表类型的话,可按如下方式操作:

复制代码 代码如下:

shell> mysqldump --all-databases --master-data=1 > data.sql

注:master-data选项缺省会打开lock-all-tables,并写入CHANGE MASTER TO语句。

如果数据库使用的是InnoDB表类型的话,则应该使用single-transcation

复制代码 代码如下:

shell> mysqldump --all-databases --single-transaction --master-data=1 > data.sql

有了数据文件,传输到从服务器上并导入:
复制代码 代码如下:

shell> mysql < data.sql

如果数据量很大的话,mysqldump会非常慢,此时直接拷贝数据文件能节省不少时间:
在拷贝之前要先锁定数据,然后再获得相关的日志信息(FILE & POSITION):
复制代码 代码如下:

mysql> FLUSH TABLES WITH READ LOCK;
mysql> SHOW MASTER STATUS;

接下来拷贝数据文件时,如果是MyISAM表类型的话,直接拷贝即可;如果是InnoDB表类型的话,一定要先停止MySQL服务再拷贝,否则拷贝文件可能无法使用。把拷贝的数据文件直接复制到从服务器的数据目录。
最后还需要再指定一下日志信息:
复制代码 代码如下:

mysql> CHANGE MASTER TO
MASTER_HOST='<MASTER_HOST>',
MASTER_USER='<SLAVE_USER>',
MASTER_PASSWORD='<SLAVE_PASSWORD>',
MASTER_LOG_FILE='<FILE>',
MASTER_LOG_POS=<POSITION>;



注:不要在my.cnf配置文件里设置MASTER_USER和MASTER_PASSWORD,因为最终生效的是CHANGE MASTER TO生成的master.info文件里的信息。

在主服务器上直接拷贝数据文件虽然很快,但需要锁表或者停止服务,这会影响线上服务。如果先前已经有了从服务器,那么可以用旧的从服务器做母本来克隆新的从服务器:

先在旧的从服务器上查询日志信息:
复制代码 代码如下:

mysql> SHOW SLAVE STATUS;



我们需要的是其中的Relay_Master_Log_File & Exec_Master_Log_Pos。

然后在旧的从服务器上按照前面的方法得到数据,并在新的从服务器上还原。

接着在新的从服务器上设置日志信息:
复制代码 代码如下:

mysql> CHANGE MASTER TO
MASTER_HOST='<MASTER_HOST>',
MASTER_USER='<SLAVE_USER>',
MASTER_PASSWORD='<SLAVE_PASSWORD>',
MASTER_LOG_FILE='<Relay_Master_Log_File>',
MASTER_LOG_POS=<Exec_Master_Log_Pos>;


不管用那个方法,最后记得在从服务器上启动复制,并检查工作是否正常:
复制代码 代码如下:

mysql> START SLAVE;
mysql> SHOW SLAVE STATUS;

如果IO线程和SQL线程都显示Yes,就可以感谢上帝了:

Slave_IO_Running 对应:Master_Log_File & Read_Master_Log_Pos

Slave_SQL_Running 对应:Relay_Master_Log_File & Exec_Master_Log_Pos

如果显示No,则说明前面某些配置步骤出错,或者对应的日志文件有问题。

故障

问题:主从复制不止何故停止了,我该怎么办?

答案:复制错误多半是因为日志错误引起的,所以首先要搞清楚是主日志错误还是中继日志错误,从错误信息里一般就能判断,如果不能可以使用类似下面的mysqlbinlog命令:
复制代码 代码如下:

shell> mysqlbinlog <MASTER_BINLOG_FILE> > /dev/null
shell> mysqlbinlog <SLAVE_BINLOG_FILE> > /dev/null

如果没有错误,则不会有任何输出,反之如果有错误,则会显示出来。
如果是主日志错误,则需要在从服务器使用SET GLOBAL sql_slave_skip_counter,如下:
复制代码 代码如下:

mysql> SET GLOBAL sql_slave_skip_counter = 1;
mysql> START SLAVE;


注:如果有多个错误,可能需要执行多次(提醒:主从服务器数据可能因此不一致)。
如果是中继日志错误,只要在从服务器使用SHOW SLAVE STATUS结果中的日志信息重新CHANGE MASTER TO即可,系统会抛弃当前的中继日志,重新下载:
复制代码 代码如下:

mysql> CHANGE MASTER TO
MASTER_LOG_FILE='<Relay_Master_Log_File>',
MASTER_LOG_POS=<Exec_Master_Log_Pos>;
mysql> START SLAVE;


至于为什么使用的是Relay_Master_Log_File & Exec_Master_Log_Pos,参见概述。
问题:主服务器宕机了,如何把从服务器提升会主服务器?
答案:在一主多从的环境总,需选择数据最新的从服务器做新的主服务器。如下图所示:

提升从服务器为主服务器

在一主(Server1)两从(Server2,、Server3)的环境中,Server1宕机后,等到Server1和Server2把宕机前同步到的日志都执行完,比较Master_Log_File和Read_Master_Log_Pos就可以判断出谁快谁慢,因为Server2从 Server1同步的数据(1582)比Server3从Server1同步的数据(1493)新,所以应该提升Server2为新的主服务器,那么 Server3在CHANGE MASTER TO到Server2的时候应该使用什么样的参数呢?1582-1493=89,而Server2的最后的二进制日志位置是8167,所以答案是 8167-89=8078。

技巧

主从服务器中的表可以使用不同的表类型。比如主服务器可以使用InnoDB表类型,提供事务,行锁等高级特性,从服务器可以使用MyISAM表类型,内存消耗少,易备份等优点。还有一个例子,一台主服务器如果同时带很多个从服务器的话,势必会影响其性能,此时可以拿出一台服务器作为从服务器代理,使用BLACKHOLE表类型,只记录日志,不写数据,由它带多台从服务器,从而提升性能。

主从服务器中的表可以使用不同的键类型。比如主服务器用InnoDB,键用VARCHAR的话节省空间,从服务器使用MyISAM,键用CHAR提高速度,因为MyISAM有静态表一说。

主从服务器中的表可以使用不同的索引。主服务器主要用来应付写操作,所以除了主键和唯一索引等保证数据关系的索引一般都可以不加,从服务器一般用来应付读操作,所以可以针对查询特征设置索引,再进一步,不同的从服务器可以针对不同的查询设置不同的索引。

工具

有一些优秀的工具可以让你的复制工作得到事半功倍的效果,详细内容请参考各自文档:

Multi-Master Replication Manager for MySQL

Percona XtraBackup

Maatkit

Tungsten-replicator

此外,Google Project Hosting里还有很多有趣的项目,可用mysql+replication标签搜索。

说明:本文参考了下面列出的书籍中相关的内容:

High Performance MySQL: Optimization, Backups, Replication, and More

MySQL High Availability: Tools for Building Robust Data Centers

(来源:火丁笔记

相关文章

  • 使用java处理字符串公式运算的方法

    使用java处理字符串公式运算的方法

    本篇文章介绍了,使用java处理字符串公式运算的方法。需要的朋友参考下
    2013-04-04
  • MySQL表的基本查询操作大全(这一篇够了)

    MySQL表的基本查询操作大全(这一篇够了)

    表的增删查改,简称表的 CURD 操作 : Create(创建),Update(更新),Retrieve(读取),Delete(删除),这篇文章主要介绍了MySQL表的基本查询操作,感兴趣的朋友一起看看吧
    2024-02-02
  • SQL中current_date()函数的实现

    SQL中current_date()函数的实现

    日期时间类型的数据也是经常要用到的,SQL中也提供了一些函数对这些数据进行处理,本文主要介绍了SQL中current_date()函数的实现,具有一定的参考价值
    2024-02-02
  • mysql利用参数sql_safe_updates限制update/delete范围详解

    mysql利用参数sql_safe_updates限制update/delete范围详解

    这篇文章主要给大家介绍了关于mysql如何利用参数sql_safe_updates限制update/delete范围的相关资料文中介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2017-10-10
  • mysql创建函数出现1418错误的解决办法

    mysql创建函数出现1418错误的解决办法

    本篇文章是对在Mysql中创建函数报“ERROR 1418”的解决方法进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • 企业生产MySQL优化介绍

    企业生产MySQL优化介绍

    这篇文章主要介绍了企业生产MySQL优化介绍的相关内容,文中叙述了其优化内容,各个方面介绍的比较详细,需要的朋友可以参考。
    2017-10-10
  • mysql登录时报socket找不到的问题及解决

    mysql登录时报socket找不到的问题及解决

    这篇文章主要介绍了mysql登录时报socket找不到的问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07
  • Mysql分库分表实现方式

    Mysql分库分表实现方式

    这篇文章详细介绍了分库分表的概念,原因,如何实现,以及不同中间件的优缺点,同时,也介绍了如何进行数据迁移和扩容缩容,以及如何处理分库分表后的ID和事务问题
    2025-02-02
  • MySQL各个特殊时间段的查询方法

    MySQL各个特殊时间段的查询方法

    在MySQL数据库中,经常需要查询某个时间段内的数据,所以本文给大家介绍了MySQL各个特殊时间段的查询方法,并提供相应的源代码示例,具有一定的参考借鉴价值,需要的朋友可以参考下
    2024-01-01
  • MySQL学习之数据库表五大约束详解小白篇

    MySQL学习之数据库表五大约束详解小白篇

    本篇文章非常适合MySQl初学者,主要讲解了MySQL数据库的五大约束及约束概念和分类,有需要的朋友可以借鉴参考下,希望可以有所帮助
    2021-09-09

最新评论