如果主从具有不同的数据库以防Mysql复制,如何重新同步Mysql DB?

Posted

技术标签:

【中文标题】如果主从具有不同的数据库以防Mysql复制,如何重新同步Mysql DB?【英文标题】:How to re-sync the Mysql DB if Master and slave have different database incase of Mysql replication? 【发布时间】:2011-01-22 21:18:20 【问题描述】:

mysql Server1 作为MASTER运行。 Mysql Server2 作为 SLAVE 运行。

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

Server2 已从网络中删除,并在 1 天后重新连接。之后主从数据库不匹配。

如何重新同步数据库,因为从 Master 到 Slave 的 DB 恢复后也不能解决问题?

【问题讨论】:

【参考方案1】:

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

【讨论】:

我认为他需要在运行脚本时暂时停止写入。 这仍然很好用。不过,这些工具已重命名,现在称为 pt-table-sync。但实际上,我发现他们的 pt-slave-restart 工具就像魔术一样工作。【参考方案2】:

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

【讨论】:

您可以检查 bin 日志,看看它们是否涵盖了您的系统不同步的时间段。如果您错过了几天,这可能是一个更大的问题,并且需要您进行完整转储以恢复丢失的数据。【参考方案3】:

当 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”输出的值。

希望这会有所帮助!

【讨论】:

这似乎坏了,因为显然你在SHOW MASTER STATUS 之前没有FLUSH TABLES WITH READ LOCK; 并转储主数据库。我认为这可能会导致例如由于您有效地将主状态设置为进行转储之前的某个时间点,因此从属设备上出现重复键错误,因此您将重播已包含在转储中的历史记录。 (如果你按照你描述的顺序做事。)【参考方案4】:

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

主宰:

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

就是这样!

【讨论】:

在定义了 INNODB 类型的 dabatase 和其他复杂的列类型(如 BLOB 和 DATE)后,我建议使用以下开关:--opt --single-transaction --comments --hex-blob --dump-date --no-autocommit --all-databases RESET_SLAVE 有必要吗?请注意,这些说明会重置复制用户和密码,因此您必须重新输入 CHANGE MASTER TO... 如果在master上调用mysqldump时使用--master-data标志,CHANGE MASTER TO命令会写入dump文件中,从而省去了导入dump文件后执行的步骤奴隶。 不锁定主服务器(不需要 Percona)plusbryan.com/mysql-replication-without-downtime 这样做的另一个好处是 SQL 转储还带有必要的“CHANGE MASTER”行(已注释掉) 有没有办法实现自动化?【参考方案5】:

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


我想使用master和slave设置mysql复制,因为我唯一知道的是它使用日志文件进行同步,如果slave离线并且不同步,理论上它应该只需要如用户 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 服务器也有意义:

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

您可以使用类似 sql 的语句:show variables like 'tmpdir'; 找出答案。

【讨论】:

两个数据库之间会自动同步吗?例如我写给Master,Slave会自动更新吗?【参考方案6】:

跟进大卫的回答...

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

【讨论】:

有什么方法可以分页输出吗? 'pager more' 我认为会做到的【参考方案7】:

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

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

从slave一次性复制:

在一个终端窗口中:

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;

如前所述导入 Dump(当然是在另一个终端中!)并输入以下命令:

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

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

【讨论】:

两个数据库之间会自动同步吗?例如我写给Master,Slave会自动更新吗?【参考方案8】:

MySQL 站点上的相关文档已经严重过时,并且充斥着各种措辞(例如 interactive_timeout)。发出带读锁的 FLUSH TABLES 作为导出主控的一部分通常只有在与存储/文件系统快照(如 LVM 或 zfs)协调时才有意义。

如果你打算使用 mysqldump,你应该改用 --master-data 选项来防止人为错误并尽快释放 master 上的锁。

假设 master 是 192.168.100.50,slave 是 192.168.100.51,每台服务器都配置了不同的 server-id,master 有二进制登录,slave 在 my.cnf 中有 read-only=1

要在导入转储后立即启动从属服务器以启动复制,请发出 CHANGE MASTER 命令但省略日志文件名和位置:

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

在 master 上发出 GRANT 以供 slave 使用:

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(在主服务器上)的替代(和默认)配置更好,因为它不太可能在从服务器上产生错误数据。

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

此进程将在 mysqldump 命令期间保持对 master 的全局锁定,但不会影响 master。

如果您想使用 mysqldump --master-data --all-databases --single-transaction(因为您只使用 InnoDB 表),那么使用 MySQL Enterprise Backup 或名为 xtrabackup 的开源实现可能会更好(由 Percona 提供)

【讨论】:

如果你想简单地重建一个现有的从站,你可以按照上面的过程,跳过几个步骤:GRANT 和手动 CHANGE MASTER 命令 问题 1:在 Windows 上,什么相当于 zcat。问题 2:就性能而言,这个 mysqldump 与大型数据库相比如何?有什么方法可以在您建议的过程中顺利使用SELECT INTO OUTFILELOAD DATA? (因为它们通常执行得更快) 过程中不需要STOP SLAVE【参考方案9】:

有时你也只需要给奴隶一脚

试试

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

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

【讨论】:

...并使用 show master status; 监视主服务器上的 Position 和使用 show slave status \G 的从属服务器上的 Exec_Master_Log_Pos: 。奴隶应该赶上主人。在短暂的网络中断后,刚刚使用 mysql 5.6 为我工作。 这是一种误导,一旦你重置了从属服务器,从属服务器就完全不知道主服务器在哪里了。【参考方案10】:

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

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

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

【讨论】:

我看到脚本总是将主日志位置设置为 1 和主日志文件的名称。我不知道是否应该对此感到担心。你能解释一下吗?我目前的职位超过 1,000,000。这是否意味着它会在加快速度之前尝试重播 100 万次查询?在对现有数据进行这些查询时是否没有损坏的可能性?我想知道为什么在执行 mysql 转储时不在脚本中使用 --master-data=2 选项,然后将文件和 pos 从转储中拉出以设置它们?【参考方案11】:

使用 LVM 重建从站

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

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

set global innodb_max_dirty_pages_pct = 0;

要监控脏页的数量运行命令

mysqladmin ext -i10 | grep dirty

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

RESET MASTER;

执行lvdisplay获取LV路径

lvdisplay

输出将如下所示

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

使用命令关闭主数据库

service mysql stop

接下来拍摄快照,mysql_snapshot 将是新的逻辑卷名。如果二进制日志放置在操作系统驱动器上,则也需要进行快照。

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 slave 正在运行,你需要停止它

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

接下来记录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

接下来启动slave MySQL

service mysql start

通过执行以下命令在从站上执行更改主命令:

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

SLAVE START;

检查从属状态:

SHOW SLAVE STATUS;

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

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

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

【讨论】:

【参考方案12】:

我很晚才回答这个问题,但是我确实遇到了这个问题,经过多次搜索,我找到了来自 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

连接到 Slave mysql 并运行如下命令: 将 MASTER 更改为 MASTER_HOST='master-server-ip', MASTER_USER='replication-user', MASTER_PASSWORD='slave-server-password', MASTER_LOG_FILE='value from above', MASTER_LOG_POS=value from above;启动奴隶;

查看 Slave 的进度: 显示奴隶状态;

如果一切正常,Last_Error 将为空,Slave_IO_State 将报告“Waiting for master to send event”。 查找 Seconds_Behind_Master,它表明它落后了多远。 YMMV。 :)

【讨论】:

这行得通,如果slave已经设置好,只是不同步,你不需要运行CHANGE MASTER;只需指定--master-data=1(或仅指定--master-data)。【参考方案13】:

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

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

【讨论】:

【参考方案14】:

大师

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;  

注意: 在 master 上,您可以运行 SET GLOBAL expire_logs_days = 3 以将 binlogs 保留 3 天,以防出现 slave 问题。

【讨论】:

以上是关于如果主从具有不同的数据库以防Mysql复制,如何重新同步Mysql DB?的主要内容,如果未能解决你的问题,请参考以下文章

主从复制原理

MySQL数据库运维之主从复制延迟问题排查

MySQL数据库运维之主从复制延迟问题排查

MySQL主从延时这么长,要怎么优化?

mysql5.5主从同步复制配置

mysql主从复制环境搭建