如果Master和slave有不同的数据库包含Mysql复制,如何重新同步Mysql DB?

问题描述 投票:128回答:13

Mysql Server1正在以MASTER身份运行。 Mysql Server2正在以SLAVE身份运行。

现在,DB复制正在从MASTER发生到SLAVE。

Server2将从网络中删除,并在1天后重新连接回来。在此之后,主站和从站中的数据库不匹配。

如何在恢复从Master到Slave的DB后再次重新同步DB也无法解决问题?

mysql database database-replication
13个回答
271
投票

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

在主人:

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;

使用此控制台命令加载主数据转储:

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

而已!


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参数(通常,对于新的/未复制的DB,默认情况下不设置),

set global server_id=4000;

现在,启动奴隶。

START SLAVE;
SHOW SLAVE STATUS\G;

输出应该与他描述的相同。

  Slave_IO_Running: Yes
  Slave_SQL_Running: Yes

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


0
投票

我用脚本创建了一个GitHub仓库来快速解决这个问题。只需更改几个变量并运行它(首先,脚本会创建数据库的备份)。

我希望这能帮助你(以及其他人)。

How to Reset (Re-Sync) MySQL Master-Slave Replication


0
投票

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

但是你需要确保丢失连接的服务器显示没有在数据库中进行任何提交,因为你得到重复键错误错误代码:1062


0
投票

使用LVM重建从站

这是我们用于使用Linux LVM重建MySQL从属的方法。这可以保证一致的快照,同时在主服务器上需要非常短的停机时间。

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

set global innodb_max_dirty_pages_pct = 0;

要监视运行该命令的脏页数

mysqladmin ext -i10 | grep dirty

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

RESET MASTER;

执行lvdisplay以获取LV Path

lvdisplay

输出将如下所示

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

使用命令关闭master数据库

service mysql stop

接下来拍一张快照,mysql快照将是新的逻辑卷名。如果在操作系统驱动器上放置了binlog,那么也需要快照。

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 *

回到主人。现在rsync将快照发送到MySQL slave

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

接下来记录binlog位置

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

接下来启动奴隶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;

确保Slave IO正在运行且没有连接错误。祝好运!

BR,车用汤

我最近在我的博客上写了这个...这里有更多细节,但故事是一样的。

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


24
投票

MySQL网站上的文档很糟糕,并且充斥着脚枪(例如interactive_timeout)。使用READ LOCK发送FLUSH表作为导出主服务器的一部分通常仅在与存储/文件系统快照(如LVM或zfs)协调时才有意义。

如果您打算使用mysqldump,则应该依赖--master-data选项来防止人为错误并尽快释放主服务器上的锁。

假设master为192.168.100.50,slave为192.168.100.51,每个服务器都配置了不同的server-id,master有二进制登录,slave在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

将replication.sql.gz文件复制到slave,然后使用zcat将其导入到slave上运行的MySQL实例:

zcat replication.sql.gz | mysql

通过向从站发出命令来启动复制:

slaveserver> START SLAVE;

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

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

如果必须(但可能不应该)过滤复制,请使用slave options replicate-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的)


17
投票

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


7
投票

我想,Maatkit utilits对你有帮助!您可以使用mk-table-sync。请看这个链接:http://www.maatkit.org/doc/mk-table-sync.html


5
投票

这是我通常在mysql slave不同步时所做的事情。我看过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
投票

跟进大卫的回答......

使用SHOW SLAVE STATUS\G将提供人类可读的输出。


5
投票

我对这个问题已经很晚了,但是我确实遇到了这个问题,经过多次搜索后,我从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”文件复制到Slave并恢复它: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 =上面的值;开始离开;

检查奴隶的进展:SHOW SLAVE STATUS;

如果一切正常,则Last_Error将为空,Slave_IO_State将报告“等待主发送事件”。寻找Seconds_Behind_Master,它表明它背后有多远。因人而异。 :)


3
投票

有时你只需要给奴隶一个踢

尝试

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

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


2
投票

这是一个完整的答案,希望能帮助别人......


我想使用master和slave设置mysql复制,因为我唯一知道的是它使用日志文件进行同步,如果奴隶脱机并且不同步,理论上它应该只需要连接回来正如用户malonso所提到的那样,对它的主人并继续从它停止的地方读取日志文件。

所以这是配置主站和从站后的测试结果,如下所示:http://dev.mysql.com/doc/refman/5.0/en/replication-howto.html ...

如果您使用推荐的主/从配置并且不写入从站,则他和我在哪里(就mysql-server 5.x而言)。我甚至不需要使用“START SLAVE;”,它只是赶上它的主人。但是有一个默认的88000每60秒重试一次,所以我想如果你筋疲力尽你可能不得不启动或重启奴隶。无论如何,对于像我这样想知道是否让一个奴隶脱机并再次备份的人需要人工干预..不,它没有。

也许原始海报在日志文件中有腐败?但最有可能的不仅仅是服务器脱机一天。


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

* FURTHER NOTES ON REPLICATION
===============================
If the MySQL server is acting as a replication slave, you should not
set --tmpdir to point to a directory on a memory-based filesystem or to
a directory that is cleared when the server host restarts. A replication
slave needs some of its temporary files to survive a machine restart so
that it can replicate temporary tables or LOAD DATA INFILE operations. If
files in the temporary file directory are lost when the server restarts,
replication fails.

你可以使用像sql这样的东西:显示像'tmpdir'这样的变量;找出来。

© www.soinside.com 2019 - 2024. All rights reserved.