如果主服务器和从服务器具有不同的数据库(如果进行Mysql复制),如何重新同步Mysql DB?


139

Mysql Server1MASTER运行。
Mysql Server2作为SLAVE运行。

现在,数据库复制正在从MASTERSLAVE进行

Server2从网络中删除,并在1天后重新连接。此后,主服务器和从服务器中的数据库不匹配。

将数据库从主服务器还原到从服务器后,如何再次重新同步数据库也不能解决问题?

Answers:


287

这是从头开始重新同步主-从复制的完整分步过程:

在大师:

RESET MASTER;
FLUSH TABLES WITH READ LOCK;
SHOW MASTER STATUS;

并将最后一条命令的结果值复制到某个地方。

在不关闭与客户端的连接的情况下(因为它将释放读取锁),发出命令以获取主服务器的转储:

mysqldump -u root -p --all-databases > /a/path/mysqldump.sql

现在,即使转储尚未结束,您也可以释放锁。为此,请在MySQL客户端中执行以下命令:

UNLOCK TABLES;

现在,使用scp或首选工具将转储文件复制到从属服务器。

在奴隶:

打开与mysql的连接,然后键入:

STOP SLAVE;

使用以下控制台命令加载master的数据转储:

mysql -uroot -p < mysqldump.sql

同步从属和主要日志:

RESET SLAVE;
CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=98;

上述字段的值是您之前复制的值。

最后,输入:

START SLAVE;

要在输入后检查一切是否再次正常运行:

SHOW SLAVE STATUS;

您应该看到:

Slave_IO_Running: Yes
Slave_SQL_Running: Yes

而已!


8
在定义了INNODB类型的dabatase和其他复杂列类型(如BLOB和DATE)之后,我建议使用以下开关:--opt --single-transaction --comments --hex-blob --dump-date --no-autocommit --all-databases
Ken Pega 2011年

4
RESET_SLAVE必要吗?请注意,这些说明会重置复制用户和密码,因此您必须使用CHANGE MASTER TO...
Mike S

25
如果在主服务器上调用mysqldump时使用--master-data标志,则将CHANGE MASTER TO命令写入转储文件中,从而节省了将转储文件导入到从属设备后执行该步骤的步骤。
2013年

3
不锁定主服务器(不需要Percona)plusbryan.com/mysql-replication-without-downtime这样做的另一个好处是SQL转储还附带了必要的“ CHANGE MASTER”行(注释掉)
mahemoff 2013年

2
有没有办法使它自动化?
Metafaniel 2015年

26

MySQL站点上的有关此文档的文档已过时,并且充满了脚步枪(例如Interactive_timeout)。通常,只有在与存储/文件系统快照(例如LVM或zfs)配合使用时,发出带有READ LOCK的FLUSH TABLE才有意义。

如果要使用mysqldump,则应改用--master-data选项来防止人为错误并尽可能快地释放master上的锁。

假设主服务器是192.168.100.50,从服务器是192.168.100.51,每个服务器都配置了不同的服务器ID,主服务器具有二进制登录名,而从服务器在my.cnf中具有只读= 1。

为了使从属服务器能够在导入转储后立即开始复制,请发出CHANGE MASTER命令,但忽略日志文件的名称和位置:

slaveserver> CHANGE MASTER TO MASTER_HOST='192.168.100.50', MASTER_USER='replica', MASTER_PASSWORD='asdmk3qwdq1';

在主机上发出GRANT,供从机使用:

masterserver> GRANT REPLICATION SLAVE ON *.* TO 'replica'@'192.168.100.51' IDENTIFIED BY 'asdmk3qwdq1';

使用压缩导出母版(在屏幕上)并自动捕获正确的二进制日志坐标:

mysqldump --master-data --all-databases --flush-privileges | gzip -1 > replication.sql.gz

将copy.sql.gz文件复制到从属服务器,然后使用zcat将其导入到在从属服务器上运行的MySQL实例:

zcat replication.sql.gz | mysql

通过向从服务器发出命令来开始复制:

slaveserver> START SLAVE;

(可选)更新从属服务器上的/root/.my.cnf,以存储与主服务器相同的root密码。

如果您使用的是5.1+版本,则最好首先将主服务器的binlog_format设置为MIXED或ROW。请注意,对于缺少主键的表,行记录的事件速度很慢。这通常比binlog_format = statement(在主服务器上)的替代(默认)配置更好,因为它不太可能在从服务器上产生错误的数据。

如果必须(但可能不应该)过滤复制,请使用从属选项plicate-wild-do-table = dbname。%或replicate-wild-ignore-table = badDB。%并仅使用binlog_format = row

在mysqldump命令期间,此过程将在主服务器上保持全局锁定,但不会以其他方式影响主服务器。

如果您很想使用mysqldump --master-data --all-databases --single-transaction(因为仅使用InnoDB表),则最好使用MySQL Enterprise Backup或称为xtrabackup的开源实现来提供更好的服务。 Percona)


3
如果您只想重建现有的从属服务器,则可以遵循上述过程,跳过几个步骤:GRANT和手动CHANGE MASTER命令
过时

问题1:在Windows上,等价于zcat。问题2:mysqldump在性能方面,这对于大型数据库有何影响?任何方式使用SELECT INTO OUTFILE,并LOAD DATA在你的建议过程顺利?(因为它们通常表现得更快)
Ifedi Okonkwo

不需要STOP SLAVE在过程中的某个地方吗?
David V.

16

除非您直接写入从服务器(Server2),否则唯一的问题应该是Server2缺少自断开连接以来发生的任何更新。只需使用“ START SLAVE;”重启从站;应该使一切恢复原状。


2
您可以检查bin日志,看看它们是否涵盖了系统不同步的时间段。如果您错过了几天,这可能是一个更大的问题,需要您执行完全转储以恢复丢失的数据。
nelaaro

7

我认为,Maatkit功用可为您提供帮助!您可以使用mk-table-sync。请查看此链接:http : //www.maatkit.org/doc/mk-table-sync.html


我认为他需要在运行脚本时暂时停止写操作。
Ztyx

这仍然很好。不过,这些工具已被重命名,现在称为pt-table-sync。但实际上,我发现他们的pt-slave-restart工具像魔术一样工作。
mlerley,2015年

7

我对这个问题很迟,但是我确实遇到了这个问题,经过大量搜索,我从布莱恩·肯尼迪(Bryan Kennedy)找到了以下信息:http : //plusbryan.com/mysql-replication-without-downtime

在Master上进行如下备份:
mysqldump --skip-lock-tables --single-transaction --flush-logs --hex-blob --master-data = 2 -A>〜/ dump.sql

现在,检查文件的开头并记下MASTER_LOG_FILE和MASTER_LOG_POS的值。稍后将需要它们: head dump.sql -n80 | grep“ MASTER_LOG”

将“ dump.sql”文件复制到从站并还原: mysql -u mysql-user -p <〜/ dump.sql

连接到Slave mysql并运行如下命令: CHANGE MASTER TO MASTER_HOST ='master-server-ip',MASTER_USER ='replication-user',MASTER_PASSWORD ='slave-server-password',MASTER_LOG_FILE ='value from above', MASTER_LOG_POS =上面的值;开始从动;

检查Slave的进度: SHOW SLAVE STATUS;

如果一切正常,Last_Error将为空,并且Slave_IO_State将报告“正在等待主机发送事件”。查找Seconds_Behind_Master,该指针指示其距离多远。YMMV。:)


3
这样就可以了,如果已经设置了从站,而只是不同步,则无需运行CHANGE MASTER;只需指定--master-data=1(或只是--master-data)即可。
LSerni '16

5

这是当mysql从站不同步时通常执行的操作。我看过mk-table-sync,但认为“风险”部分看起来很恐怖。

在大师:

SHOW MASTER STATUS

输出的列(文件,位置)将对我们有用。

在从站上:

STOP SLAVE

然后转储主数据库并将其导入到从数据库。

然后运行以下命令:

CHANGE MASTER TO
  MASTER_LOG_FILE='[File]',
  MASTER_LOG_POS=[Position];
START SLAVE;

其中[File]和[Position]是从上方显示的“ SHOW MASTER STATUS”输出的值。

希望这可以帮助!


5
这似乎是无效的,因为显然您不需要FLUSH TABLES WITH READ LOCK;SHOW MASTER STATUS转储master数据库。我认为这可能会导致例如从属服务器上出现重复的键错误,因为您将主服务器状态有效地设置为进行转储之前的某个时间点,因此您将重播已包含在转储中的历史记录。(如果您按照描述的顺序进行操作。)
KajMagnus


3

有时候你也只需要给奴隶踢一下

尝试

stop slave;    
reset slave;    
start slave;    
show slave status;

很多时候,奴隶,他们只是被卡住了:)


...和显示器Position上使用主show master status;反对Exec_Master_Log_Pos:使用奴隶show slave status \G。奴隶应该赶上主人。短暂的网络中断后,立即使用mysql 5.6为我工作。
Mike S

10
这是一种误导,一旦您重置从属设备,从属设备将完全失去有关主设备位置的知识。
钱琛

2

这是一个完整的答案,有望对其他人有所帮助...


我想使用主服务器和从服务器设置mysql复制,并且由于我唯一了解的是它使用日志文件进行同步,因此如果从服务器脱机并失去同步,从理论上讲,它只需要重新连接即可正如其用户malonso所提到的,并继续从其中断处读取日志文件。

因此,这是配置主机和从机后的测试结果,具体方法如下:http : //dev.mysql.com/doc/refman/5.0/en/replication-howto.html ...

只要您使用推荐的主/从配置,并且不写从服务器,他和我就在正确的位置(就mysql-server 5.x而言)。我什至不需要使用“ START SLAVE;”,它赶上了它的主人。但是默认情况下,每60秒会有88000次重试,所以我想如果您精疲力尽,可能必须启动或重新启动从属服务器。无论如何,对于像我这样想知道是否有奴隶脱机并再次备份的人,需要人工干预。.不,不是。

也许原始海报的日志文件已损坏?但是,很可能不仅仅是服务器离线一天。


从/usr/share/doc/mysql-server-5.1/README.Debian.gz提取,这对非debian服务器也可能有意义:

*有关复制的更多说明
==============================
如果MySQL服务器充当复制从站,则不应
将--tmpdir设置为指向基于内存的文件系统上的目录或
服务器主机重新启动时清除的目录。复制
从站需要一些临时文件才能在机器重启后幸存下来,因此
它可以复制临时表或LOAD DATA INFILE操作。如果
重新启动服务器后,临时文件目录中的文件会丢失,
复制失败。

您可以使用类似sql的东西:显示类似'tmpdir'的变量;找出答案。


两个数据库之间是否会自动自动同步?例如,我写给主人,奴隶会自动更新吗?
TransformBinary

2

添加到流行的答案以包括此错误:

"ERROR 1200 (HY000): The server is not configured as slave; fix in config file or with CHANGE MASTER TO",

从奴隶复制一枪:

在一个终端窗口中:

mysql -h <Master_IP_Address> -uroot -p

连接后

RESET MASTER;
FLUSH TABLES WITH READ LOCK;
SHOW MASTER STATUS;

状态显示如下:请注意,职位编号有所不同!

+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 |      98  | your_DB      |                  |
+------------------+----------+--------------+------------------+

导出转储,类似于他描述的“ 使用另一个终端 ”!

退出并连接到您自己的数据库(从数据库):

mysql -u root -p

输入以下命令:

STOP SLAVE;

如前所述导入转储(当然,在另一个终端中!)并键入以下命令:

RESET SLAVE;
CHANGE MASTER TO 
  MASTER_HOST = 'Master_IP_Address', 
  MASTER_USER = 'your_Master_user', // usually the "root" user
  MASTER_PASSWORD = 'Your_MasterDB_Password', 
  MASTER_PORT = 3306, 
  MASTER_LOG_FILE = 'mysql-bin.000001', 
  MASTER_LOG_POS = 98; // In this case

记录后,设置server_id参数(通常,对于新的/非复制的数据库,默认情况下未设置),

set global server_id=4000;

现在,启动从站。

START SLAVE;
SHOW SLAVE STATUS\G;

输出应与他描述的相同。

  Slave_IO_Running: Yes
  Slave_SQL_Running: Yes

注意:复制后,主服务器和从服务器共享相同的密码!


两个数据库之间是否会自动自动同步?例如,我写给主人,奴隶会自动更新吗?
TransformBinary

1

使用LVM重建从站

这是我们使用Linux LVM重建MySQL从站的方法。这样可以确保快照一致,同时在主服务器上需要最少的停机时间。

在主MySQL服务器上将innodb最大脏页百分比设置为零。这将迫使MySQL将所有页面写入磁盘,这将大大加快重启速度。

set global innodb_max_dirty_pages_pct = 0;

要监视脏页数,请运行以下命令

mysqladmin ext -i10 | grep dirty

一旦数字停止减少,您就可以继续了。接下来重置主服务器,以清除旧的bin日志/中继日志:

RESET MASTER;

执行lvdisplay获取LV路径

lvdisplay

输出将如下所示

--- Logical volume ---
LV Path                /dev/vg_mysql/lv_data
LV Name                lv_data
VG Name                vg_mysql

使用命令关闭master数据库

service mysql stop

接下来进行快照,mysql_snapshot将是新的逻辑卷名称。如果将二进制日志放置在OS驱动器上,则也需要对其进行快照。

lvcreate --size 10G --snapshot --name mysql_snapshot /dev/vg_mysql/lv_data

使用命令再次启动master

service mysql start

将脏页设置恢复为默认值

set global innodb_max_dirty_pages_pct = 75;

再次运行lvdisplay以确保快照在其中并且可见

lvdisplay

输出:

--- Logical volume ---
LV Path                /dev/vg_mysql/mysql_snapshot
LV Name                mysql_snapshot
VG Name                vg_mysql

挂载快照

mkdir /mnt/mysql_snapshot
mount /dev/vg_mysql/mysql_snapshot /mnt/mysql_snapshot

如果您有一个正在运行的MySQL从站,则需要停止它

service mysql stop

接下来,您需要清除MySQL数据文件夹

cd /var/lib/mysql
rm -fr *

回到高手。现在将快照同步到MySQL从站

rsync --progress -harz /mnt/mysql_snapshot/ targethostname:/var/lib/mysql/

rsync完成后,您可以卸载并删除快照

umount /mnt/mysql_snapshot
lvremove -f /dev/vg_mysql/mysql_snapshot

如果旧的复制用户不存在或密码未知,则在主服务器上创建复制用户

GRANT REPLICATION SLAVE on *.* to 'replication'@'[SLAVE IP]' identified by 'YourPass';

验证/ var / lib / mysql数据文件是否为mysql用户所有,如果是这样,则可以省略以下命令:

chown -R mysql:mysql /var/lib/mysql

接下来记录二进制日志位置

ls -laF | grep mysql-bin

您会看到类似

..
-rw-rw----     1 mysql mysql  1073750329 Aug 28 03:33 mysql-bin.000017
-rw-rw----     1 mysql mysql  1073741932 Aug 28 08:32 mysql-bin.000018
-rw-rw----     1 mysql mysql   963333441 Aug 28 15:37 mysql-bin.000019
-rw-rw----     1 mysql mysql    65657162 Aug 28 16:44 mysql-bin.000020

在这里,主日志文件是顺序中最高的文件编号,而bin日志位置是文件大小。记录以下值:

master_log_file=mysql-bin.000020
master_log_post=65657162

接下来启动slave MySQL

service mysql start

通过执行以下操作在从属服务器上执行change master命令:

CHANGE MASTER TO 
master_host="10.0.0.12", 
master_user="replication", 
master_password="YourPass", 
master_log_file="mysql-bin.000020", 
master_log_pos=65657162; 

终于开始奴隶

SLAVE START;

检查从站状态:

SHOW SLAVE STATUS;

确保从站IO正在运行,并且没有连接错误。祝好运!

BR,Juha Vehnia

我最近在自己的博客上写了这篇文章,这里的博客...那里没有更多细节,但是故事是一样的。

http://www.juhavehnia.com/2015/05/rebuilding-mysql-slave-using-linux-lvm.html


0

我使用脚本创建了GitHub存储库以快速解决此问题。只需更改几个变量并运行它(首先,脚本将创建数据库的备份)。

希望对您(以及其他人)有所帮助。

如何重置(重新同步)MySQL主从复制


我看到脚本始终将主日志位置设置为1,并将主日志文件的名称设置为。我不太了解该不该担心。你能解释一下吗?我目前的职位超过1,000,000。这是否意味着它会在加快速度之前尝试重播100万个查询?对现有数据进行这些查询时,不会有损坏的机会吗?我想知道为什么在进行mysql转储时在脚本中不使用--master-data = 2选项,然后从转储中拉出文件和pos进行设置?
乔西亚

0

我们使用的是MySQL的主复制复制技术,如果一台MySQL服务器说从网络中删除了1个,则它会在恢复连接并传输网络中服务器2中已提交的所有记录后重新连接自身。到恢复后失去连接的服务器1。默认情况下,每60秒,MySQL中的从属线程将重试以连接到其主服务器。可以将此属性更改为MySQL,并带有“ master_connect_retry = 5”标志,其中5以秒为单位。这意味着我们希望每5秒重试一次。

但是,您需要确保丢失连接的服务器显示在您得到重复时不会在数据库中进行任何提交。关键错误错误代码:1062


0

硕士

mysqldump -u root -p --all-databases --master-data | gzip > /tmp/dump.sql.gz  

scp master:/tmp/dump.sql.gz slave:/tmp/ 将转储文件移动到从属服务器

奴隶:

STOP SLAVE;

zcat /tmp/dump.sql.gz | mysql -u root -p

START SLAVE;
SHOW SLAVE STATUS;  

注意
在主服务器上SET GLOBAL expire_logs_days = 3,如果从服务器出现问题,您可以运行3天来保留二进制日志。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.