Your SlideShare is downloading. ×
MySQL 同步6 MySQL 同步同步功能在 MySQL 3.23.15 就开始引进了,它可以把一个 MySQL 服务器上的数据复制到另一个服务器上去。本章描述了 MySQL 的各种复制特性。介绍了同步的概念,如何设置同步服务器,以及可用服务...
•   有了 master/slave 机制后,就更稳健了。当 master 上发生问题时,可以把 slave 作为备用切换过去。•   可以在 slave 和 master 之间分担一些查询,这就能加速响应时间。SELECT 查询就可以在 s...
slave 上已经完整拷贝 master 数据后,就可以连接到 master 上然后等待处理更新了。如果 master 当机或者slave 连接断开,slave 会定期尝试连接到 master 上直到能重连并且等待更新。重试的时间间隔由    ...
下例说明了   SHOW PROCESSLIST     结果中的 3 个线程是什么样的。这是在 MySQL 4.0.15 及更新上执行SHOW PROCESSLIST    的结果,State 字段的内容已经比旧版本显示的更有意义了。在 ma...
User: system user    Host:      db: NULL Command: Connect    Time: 11   State: Waiting for master to send event    Info: N...
以下列出了 master 的   Binlog Dump    线程   State   字段中最常见的几种状态。如果在 master 上没有 Binlog Dump   线程,那么同步就没有在运行。也就是说,没有 slave 连接上来。Sen...
Requesting binlog dump确定连接到 master 后出现的一个短暂的状态。该线程向 master 发送一个请求,告诉它要请求的二进制文件以及开始位置。        Waiting to reconnect after a ...
Waiting for slave mutex on exit  当前线程停止了,这个时间很短。 6.3.3 Slave 的 SQL 线程状态 以下列出了 slave 的 SQL 线程   State   字段中最常见的几种状态:Reading...
中继日志和二进制日志的格式一样,因此也可以用               mysqlbinlog   来读取。当 SQL 线程读取完中继日志中的全          部事件后就不再需要它了,会自动删除它。中继日志没有显式的删除机制,因为 SQL...
Line                                 Description  1                               Master_Log_File  2                      ...
5                                   Master_User   6                    Password (not shown by   SHOW SLAVE STATUS )   7   ...
2                                Relay_Log_Pos      3                            Relay_Master_Log_File      4             ...
想要完全掌握 MySQL 同步设置,最好把本章全部读完,并且测试在"14.6.1 SQL Statements for Controlling Master Servers"和"14.6.2 SQL Statements for Control...
o   授予全局   SUPER   和   RELOAD   权限。o   授予对想要加载的所有表上的          SELECT     权限。在 master 上任何没有   SELECT   权限的表都会被   LOAD    DA...
可能不需要同步      mysql   数据库,因为在 slave 上的权限表和 master 不一样。这时,解开压缩包的时候要排除它。同时在压缩包中也不要包含任何日志文件,或者                `master.info~ 或 ...
mysql> SHOW MASTER STATUS;  尽快记下     SHOW MASTER STATUS     显示结果中的日志文件及偏移位置。然后,在不解锁的情况下关闭  master,确保 master 上的快照和记录的结果一致: ...
slave_id    的值和   master_id   类似,是 1 到 2^32-1 之间的正整数。另外,这个 ID 必须不能和 master  的 ID 一样。例如:   [mysqld]   server-id=2  如果有多个 sl...
19.mysql> CHANGE MASTER TO 20.      ->      MASTER_HOST=master_host_name, 21.      ->      MASTER_USER=replication_user_na...
we force server id to 2, but this MySQL server will not act as a slave.如果因为其他原因不能同步的话,错误信息也会记录在 slave 的日志上。一旦 slave 开始同步了,...
下表展示了不同版本的 MySQL 之间的 master/slave 同步兼容性。                                Master                Master             Master   ...
通过以下步骤可以实现安全地升级,假定 master 要升级到 3.23,而 slave 已经是 4.0 或 4.1 了。注意,master 升 级后,不要重启使用任何旧的二进制日志的同步,因为它会干扰到 4.0 或 4.1 slave 的同步。...
把 master 从 MySQL 3.23,4.0 或 4.1 升级到 5.0.0 时,首先要确认这个 master 的所有 slave 都已经是 5.0.0       了,否则的话,要先升级 slave:挨个关闭,升级,重启,重启同步等。5...
•   从 MySQL 4.0.14 开始同步   FOREIGN_KEY_CHECKS     变量。从 5.0.0 开始同步   sql_mode ,    UNIQUE_CHECKS ,和 SQL_AUTO_IS_NULL      变量...
•   在 master 上执行的     CREATE TABLE   语句如果包括了       DATA DIRECTORY 或 INDEX DIRECTORY         子句,    那么它也会应用于 slave 上。如果 sla...
2. 使用 SHOW STATUS 语句检查变量 Slave_open_temp_tables 的值。            3. 如果它的值是 0,运行 mysqladmin shutdown 命令关闭 slave。            4...
•   也可以放心地关闭 slave(干净地),它会记录停止的地方。不干净地关闭 slave 可能产生问题,特别是系统关闭了但缓存    还没刷新到磁盘时。可以提供不间断电源来提高系统容错性。master 的不干净关闭可能导致表和二进制内容的不...
•   LOAD DATA LOCAL INFILE   不再像以前 3.23 那样被略过了。•   在 3.23 中,RAND() 更新同步不正常。因此在使用           RAND()   更新时采用   RAND(some_non_...
从 MySQL 4.1.1 开始,一下选项也按照上述方式特殊处理:•   --master-ssl•   --master-ssl-ca•   --master-ssl-capath•   --master-ssl-cert•   --mast...
假定在   `my.cnf` 设定了以下选项值: [mysqld] master-host=some_host第一次启动 slave 的时候,它从       `my.cnf` 中读取选项值,然后再把它们保存在 `master.info` 中。...
下列所述启动选项都是用来控制同步的:它们中的大部分都可以在运行时用                  CHANGE MASTER TO   语句来改变。 其他的,例如   --replicate-* ,只能在 salve 启动时指定。我们打算在...
master 服务器的主机名或者 ip 地址。如果没有设置它,slave 线程无法启动。如果存在的话,`master.info`文件中选项值优先被读取。          --master-info-file= file_nameslave 记...
中继日志自动轮转(rotate)的大小。详情请看"5.2.3 Server System Variables"。这个选项是从 MySQL 4.0.14之后才可以用的。                          --read-only这个...
前就是这样)。不要设置     --relay-log-space-limit     的值小于 2 倍     --max-relay-log-size(如果   --max-relay-log-size   的值为 0,则是   --max...
告诉 slave 只同步那些指定的数据表。想要指定更多的数据表,只需多次使用该选项,每次指定一个数据表。这个选项支持跨库更新,和      --replicate-do-db   选项相反。请仔细阅读最后面的注意事项。             ...
--                                                                    replicat                                            ...
wi                                                                         ld                                             ...
-rewrite-                                                                           db= from_n                            ...
个配置 master 还不能直接从 TCP/IP 套接字中读取 slave 的 IP 地址。因为存在   NAT   或者其他路由机制,这个IP 信息还不足以在 master 或者其他主机上连接到 slave 上。这个选项是从 MySQL 4....
salve 放弃读之后等待多少秒再次从 master 读取更多的数据,考虑到了连接断开,尝试重连的情况。第一次重试  会在超时后立刻执行。重试的时间间隔由选项             --master-connect-retry   控制。  ...
o    是:测试   --binlog-do-db   和   --binlog-ignore-db   选项(详情请看"5.9.4 The Binary     Log")。测试结果?    忽略:忽略并且退出。    执行:不立刻执行...
o    否:走到下一步。4. 是否有 --replicate-ignore-table 规则?o    是:这个表是否匹配这些规则?    是:忽略并且退出。    否:走到下一步。o    否:走到下一步。5. 是否有 --replic...
6. 是否有 --replicate-wild-ignore-table 规则?o    是:这个表是否匹配这些规则?    是:忽略并且退出。    否:走到下一步。o    否:走到下一步。7. 没有匹配 --replicate-*-t...
答: 需要设计几个选项参数。如果已经有了 master 的备份并且记录了数据快照二进制日志文件名以及偏移位置(运 行    SHOW MASTER STATUS   查看结果),执行以下步骤:1. 确定 slave 指定了一个唯一的服务器编号。...
4. shell> tar zcf /tmp/backup.tar.gz /var/lib/mysql5. 执行以下语句,记录下输出的结果,后面要用到: 6. mysql> SHOW MASTER STATUS;7. 释放锁:   mysql>...
答:不,非必需。slave 可以好几小时甚至几天关闭或者不连接 master,然后重连再取得更新操作日志。例如,可以在拨号链接上设置一个 mater/slave 关系,拨号可能只是零星的不定期的连接。这种做法隐含的是,在任何指定的时间里,除非使...
1. 在 master 上,执行以下语句: 2. mysql> FLUSH TABLES WITH READ LOCK;   mysql> SHOW MASTER STATUS;  记录下结果中的日志文件名以及偏移位置,它们是同步的坐标值。3....
master 1 上去。这意味着除非能确保所有的更新都能以任何顺序安全地执行,否则不要使用双向同步,或者除非注意在客户端程序中的不知原因的无序更新操作。同时也要意识到在所关心的更新问题上,双向同步实际上并不能很大地改善性能(甚至没有)。两个服务...
•   safe_writer_connect()•   safe_reader_connect()•   safe_reader_statement()•   safe_writer_statement()       每个函数名的   sa...
答:MySQL 同步对于频繁读但不频繁写的系统很有好处。理论上来讲,使用单一 master/多 slave 的配置,就可以通过这个方法来衡量系统:增加更多的 slave 直到用完所有的网络带宽或者 master 的更新操作增长到了不能再处理的点...
writes = 1200 / (2 + 9/(N+1))      最后的等式说明了 N 个 slave 的最大写数量,给它每分钟的最高读频率 1200 和 1 次写 9 次读的机率。      分析结论比率如下:•   如果 N = 0(意...
问:如何利用同步提供冗余/高可用性?             答:使用当前已经可用的特性,可以配置一个 master 和一个(或多个)slave,并且写一个脚本监控 master 是否运             行着。然后通知应用程序和 sla...
M 表示 masetr,S 表示 slave,WC 表示提交读写操作的客户端;只提交读操作的客户端没有表示出来,因为它们无需切换。S1,S2,S3 都是使用--log-bin      选项,不用   --log-slave-updates  ...
|            |          v v            S1<--S2   S3             ^        |             +-------+    当 M 又起来了之后,只需在 M 上提交和在...
Slave_IO_Running   和   Slave_SQL_Running   的值是否都是。如果不是,确定是否用同步参数启动 slave    服务器了。•   如果 slave 正在运行,它是否建立了到 master 的连接?运行  ...
5. 如果确定 slave 精确地同步 master 了,并且没有除了 slave 线程之外的对数据表的更新操作,则推断这是因     为 bug 产生的差异。如果是使用最近的版本,请报告这个问题,如果使用的是旧版本,试着升级一下。 6.11 ...
o    发现问题时,在 master 上执行          SHOW MASTER STATUS   的结果       o    发现问题时,在 master 上执行          SHOW SLAVE STATUS   的结果  ...
我想问一下,数据库同步需要库中的表结构相同,那么我能不能在 Master 上的表中的某个字段不设索引,而在            slave 上建索引?            还有同步会不会将 Slave 中已经存在的数据删除掉(这些数据的 k...
老规矩,先贴上报错     老规矩,先贴上报错信息,mysql 版本,配置等资料。     MySQL 中文网: http://imysql.cn     Google MySQL 中文用户群:http://groups.google.com/...
My sql 同步
My sql 同步
My sql 同步
My sql 同步
My sql 同步
My sql 同步
My sql 同步
My sql 同步
My sql 同步
My sql 同步
My sql 同步
Upcoming SlideShare
Loading in...5
×

My sql 同步

1,392

Published on

Published in: Technology
0 Comments
5 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,392
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
0
Comments
0
Likes
5
Embeds 0
No embeds

No notes for slide

Transcript of "My sql 同步"

  1. 1. MySQL 同步6 MySQL 同步同步功能在 MySQL 3.23.15 就开始引进了,它可以把一个 MySQL 服务器上的数据复制到另一个服务器上去。本章描述了 MySQL 的各种复制特性。介绍了同步的概念,如何设置同步服务器,以及可用服务器的参照。还提供了一系列的常见问题及其答案,疑难解答。"14.6 Replication Statements"中介绍了同步相关的 SQL 语句语法。我们建议经常访问"http://www.mysql.com"经常阅读本章的最新内容。同步功能一直在改进,我们经常把这部分的手册更新到当前的最新内容。6.1 同步介绍MySQL 3.23.15 及更高的版本支持单向同步。一个服务器作为 master(主服务器),一个或者多个服务器作为slave(从服务器)。master 服务器把更新的内容写到二进制日志(binary log 或 binlog)中,并且维护了一个索引文件来记录日志循环的情况。这些日志中的更新部分会被发送到 slave 服务器。一个 slave 连接到 master 之后,它通知 master 最后一次成功增量更新的日志位置。slave 会找出所有从那个时刻开始的更新操作,然后阻塞并等待master 发送新的更新操作。如果想要做一个同步服务器链的话,slave 同时也可以作为 master。注意,启用同步后,所有要同步的更新操作都必须在 master 上执行。否则,必须注意不要造成用户在 master 上的更新和在 slave 上的更新引起冲突。单向同步的好处是稳健,高速,系统易管理:
  2. 2. • 有了 master/slave 机制后,就更稳健了。当 master 上发生问题时,可以把 slave 作为备用切换过去。• 可以在 slave 和 master 之间分担一些查询,这就能加速响应时间。SELECT 查询就可以在 slave 上执行以减少 master 的负载。更新数据的语句则要放在 mater 上执行以保持 master 和 slave 的同步。当非更新操作占多数时,负载均衡就很 有效了,不过这只是普通情况而言。• 另一个好处是可以在 slave 上备份数据,无需干扰 master。备份数据时 master 照样继续运作。详情请看"5.7.1 Database Backups"。 6.2 同步机制实现概述 MySQL 同步机制基于 master 把所有对数据库的更新、删除 等)都记录在二进制日志里。因此,想要启用同步机制, 在 master 就必须启用二进制日志。详情请看"5.9.4 The Binary Log"。 每个 slave 接受来自 master 上在二进制日志中记录的更新操作,因此在 slave 上执行了这个操作的一个拷贝。 应该非常重要地意识到,二进制日志只是从启用二进制日志开始的时刻才记录更新操作的。所有的 slave 必须在启 用二进制日志时把 master 上已经存在的数据拷贝过来。如果运行同步时 slave 上的数据和 master 上启用二进制 日志时的数据不一致的话,那么 slave 同步就会失败。 把 master 上的数据拷贝过来的方法之一实在 slave 上执行 LOAD DATA FROM MASTER 语句。不过要注意, LOAD DATA FROM MASTER 是从 MySQL 4.0.0 之后才开始可以用的,而且只支持 master 上的 MyISAM 类型表。同样地,这个操作需要一个全局的读锁,这样的话传送日志到 slave 的时候在 master 上就不会有更新操作 了。当实现了自由锁表热备份时(在 MySQL 5.0 中),全局读锁就没必要了。 由于有这些限制,因此我们建议只在 master 上相关数据比较小的时候才执行 LOAD DATA FROM MASTER 语句,或者在 master 上允许一个长时间的读锁。由于每个系统之间 LOAD DATA FROM MASTER 的速度各 不一样,一个比较好的衡量规则是每秒能拷贝 1MB 数据。这只是的粗略的估计,不过 master 和 slave 都是奔腾 700MHz 的机器且用 100MBit/s 网络连接时就能达到这个速度了。
  3. 3. slave 上已经完整拷贝 master 数据后,就可以连接到 master 上然后等待处理更新了。如果 master 当机或者slave 连接断开,slave 会定期尝试连接到 master 上直到能重连并且等待更新。重试的时间间隔由 --master-connect-retry 选项来控制,它的默认值是 60 秒。每个 slave 都记录了它关闭时的日志位置。msater 是不知道有多少个 slave 连接上来或者哪个 slave 从什么时候开始更新。6.3 同步实现细节MySQL 同步功能由 3 个线程(master 上 1 个,slave 上 2 个)来实现。执行 START SLAVE 语句后,slave 就创建一个 I/O 线程。 线程连接到 master 上,并请求 master 发送二进制日志中的语句。 I/O master 创建一个线程来把日志的内容发送到 slave 上。这个线程在 master 上执行 SHOW PROCESSLIST 语句后的结果中的 BinlogDump 线程便是。slave 上的 I/O 线程读取 master 的 Binlog Dump 线程发送的语句,并且把它们拷贝到其数据目录下的中继日志(relay logs)中。第三个是 SQL 线程,salve 用它来读取中继日志,然后执行它们来更新数据。如上所述,每个 mster/slave 上都有 3 个线程。每个 master 上有多个线程,它为每个 slave 连接都创建一个线程,每个 slave 只有 I/O 和 SQL 线程。在 MySQL 4.0.2 以前,同步只需 2 个线程(master 和 slave 各一个)。slave 上的 I/O 和 SQL 线程合并成一个了,它不使用中继日志。slave 上使用 2 个线程的优点是,把读日志和执行分开成 2 个独立的任务。执行任务如果慢的话,读日志任务不会跟着慢下来。例如,如果 slave 停止了一段时间,那么 I/O 线程可以在 slave 启动后很快地从 master 上读取全部日志,尽管 SQL 线程可能落后 I/O 线程好几的小时。如果 slave 在 SQL 线程没全部执行完就停止了,但 I/O 线程却已经把所有的更新日志都读取并且保存在本地的中继日志中了,因此在 slave 再次启动后就会继续执行它们了。这就允许在master 上清除二进制日志,因为 slave 已经无需去 master 读取更新日志了。执行 SHOW PROCESSLIST 语句就会告诉我们所关心的 master 和 slave 上发生的情况。
  4. 4. 下例说明了 SHOW PROCESSLIST 结果中的 3 个线程是什么样的。这是在 MySQL 4.0.15 及更新上执行SHOW PROCESSLIST 的结果,State 字段的内容已经比旧版本显示的更有意义了。在 master 上,SHOW PROCESSLIST 的结果如下: mysql> SHOW PROCESSLISTG *************************** 1. row *************************** Id: 2 User: root Host: localhost:32931 db: NULL Command: Binlog Dump Time: 94 State: Has sent all binlog to slave; waiting for binlog to be updated Info: NULL在这里,线程 2 是为一个 slave 连接创建的。结果表明所有未完成的更新日志已经都发送到 slave 了,master 正等待新的更新日志发生。在 slave 上,SHOW PROCESSLIST 的结果如下: mysql> SHOW PROCESSLISTG *************************** 1. row *************************** Id: 10
  5. 5. User: system user Host: db: NULL Command: Connect Time: 11 State: Waiting for master to send event Info: NULL *************************** 2. row *************************** Id: 11 User: system user Host: db: NULL Command: Connect Time: 11 State: Has read all relay log; waiting for the slave I/O thread to update it Info: NULL这表明线程 10 是 I/O 线程,它正连接到 master 上;线程 11 是 SQL 线程,它执行中继日志中的更新操作。现在,这 2 个线程都处于空闲状态,正等待新的更新日志。注意,Time 字段的值告诉我们 slave 上的日志比 master 晚了多久。详情请看"6.9 Replication FAQ"。6.3.1 Master 同步线程状态
  6. 6. 以下列出了 master 的 Binlog Dump 线程 State 字段中最常见的几种状态。如果在 master 上没有 Binlog Dump 线程,那么同步就没有在运行。也就是说,没有 slave 连接上来。Sending binlog event to slave 事件是由二进制日志构成,一个事件通常由更新语句加上其他信息。线程读取到一个事件并正发送到 slave 上。 Finished reading one binlog; switching to next binlog 读取完了一个二进制日志,正切换到下一个。 Has sent all binlog to slave; waiting for binlog to be updated 已经读取完全部未完成更新日志,并且全部都发送到 slave 了。它处于空闲状态,正等待在 master 上执行新的更 新操作以在二进制日志中产生新的事件,然后读取它们。 Waiting to finalize termination 当前线程停止了,这个时间很短。 6.3.2 Slave 的 I/O 线程状态 以下列出了 slave 的 I/O 线程 State 字段中最常见的几种状态。从 MySQL 4.1.1 开始,这个状态在执行 SHOW SLAVE STATUS 语句结果的 Slave_IO_State 字段也会出现。这意味着可以只执行 SHOW SLAVE STATUS 语句就能了解到更多的信息。Connecting to master 该线程证尝试连接到 master 上。 Checking master version 确定连接到 master 后出现的一个短暂的状态。 Registering slave on master 确定连接到 master 后出现的一个短暂的状态。
  7. 7. Requesting binlog dump确定连接到 master 后出现的一个短暂的状态。该线程向 master 发送一个请求,告诉它要请求的二进制文件以及开始位置。 Waiting to reconnect after a failed binlog dump request如果二进制日志转储(binary log dump)请求失败了(由于连接断开),该线程在休眠时进入这个状态,并定期重连。重连的时间间隔由 --master-connect-retry 选项来指定。 Reconnecting after a failed binlog dump request该线程正尝试重连到 master。 Waiting for master to send event已经连接到 master,正等待它发送二进制日志。如果 master 闲置时,这个状态可能会持续较长时间,如果它等待超过 slave_read_timeout 秒,就会发生超时。这时,它就会考虑断开连接,然后尝试重连。 Queueing master event to the relay log已经读取到一个事件,正把它拷贝到中继日志中以备 SQL 线程处理。 Waiting to reconnect after a failed master event read读日志时发生错误(由于连接断开)。该线程在重连之前休眠 master-connect-retry 秒。 Reconnecting after a failed master event read正尝试重连到 master。当连接确定后,状态就变成 Waiting for master to send event 。 Waiting for the slave SQL thread to free enough relay log spacerelay_log_space_limit 的值非零,中继日志的大小总和超过这个值了。I/O 线程等待 SQL 线程先处理中继日志然后删除它们以释放足够的空间。
  8. 8. Waiting for slave mutex on exit 当前线程停止了,这个时间很短。 6.3.3 Slave 的 SQL 线程状态 以下列出了 slave 的 SQL 线程 State 字段中最常见的几种状态:Reading event from the relay log 从中继日志里读到一个事件以备执行。 Has read all relay log; waiting for the slave I/O thread to update it 已经处理完中继日志中的全部事件了,正等待 I/O 线程写入更新的日志。 Waiting for slave mutex on exit 当前线程停止了,这个时间很短。 SQL 线程的 State 字段有时候也可能是一个 SQL 语句。这意味着它从中继日志中读取到一个事件了,从中提取出 SQL 语句,并执行它。 6.3.4 中继日志及状态文件 默认地,中继日志的名字格式为 `host_name-relay-bin.nnn`,host_name 是服务器的主机名,nnn 是序 号。中继日志是根据顺序的序号来创建的,从 000001 (MySQL 4.0 及更旧是 001 )开始。slave 上用一个索引文 件来跟踪当前正在使用的中继日志。默认的中继日志索引文件名是 `host_name-relay-bin.index`。默认地, 这个文件位于 slave 的数据文件目录下。默认文件名可以根据的系统选项 --relay-log 和 --relay- log-index 来替换。详情请看"6.8 Replication Startup Options"。
  9. 9. 中继日志和二进制日志的格式一样,因此也可以用 mysqlbinlog 来读取。当 SQL 线程读取完中继日志中的全 部事件后就不再需要它了,会自动删除它。中继日志没有显式的删除机制,因为 SQL 线程会自动关注这个。不过,从 MySQL 4.0.14 开始,执行 FLUSH LOGS 的话就会轮转(rotate)中继日志,会让 SQL 线程删除它们。 在下列条件中会创建一个新的中继日志:• slave 启动后,I/O 线程第一次启动(在 MySQL 5.0 中,每次 I/O 线程启动后都会新建一个中继日志,而不只是第一次 启动时)。• 刷新日志时;例如,执行 FLUSH LOGS 语句或运行 mysqladmin flush-logs 命令(从 MySQL 4.0.14 开 始才会创建新中继日志)。• 当前的中继日志大小太大了;"太大了"是这么判断的: o max_relay_log_size , 如果 max_relay_log_size > 0 的话 o max_binlog_size , 如果 max_relay_log_size = 0 或 MySQL 低于 4.0.14 slave 会在数据文件目录下创建两个额外的文件。它们是状态文件,名字默认为 `master.info` and `relay- log.info`。它们的内容跟执行 SHOW SLAVE STATUS 语句的结果类似。详情请看"14.6.2 SQL Statements for Controlling Slave Servers"。由于是磁盘上的文件,它们在 slave 关闭后还会留着。下一次 slave 启动时,就会读取这两个文件来判断从 master 读取到二进制日志的什么位置了,处理中继日志到什么位置了。 `master.info` 文件由来 I/O 线程更新。在 MySQL 4.1 以前,文件的内容和执行 SHOW SLAVE STATUS 语句结果中相对应的字段值一样,如下:
  10. 10. Line Description 1 Master_Log_File 2 Read_Master_Log_Pos 3 Master_Host 4 Master_User 5 Password (not shown by SHOW SLAVE STATUS ) 6 Master_Port 7 Connect_Retry从 MySQL 4.1 开始,文件内容还包括了 SSL 选项: Line Description 1 Number of lines in the file 2 Master_Log_File 3 Read_Master_Log_Pos 4 Master_Host
  11. 11. 5 Master_User 6 Password (not shown by SHOW SLAVE STATUS ) 7 Master_Port 8 Connect_Retry 9 Master_SSL_Allowed 10 Master_SSL_CA_File 11 Master_SSL_CA_Path 12 Master_SSL_Cert 13 Master_SSL_Cipher 14 Master_SSL_Key`relay-log.info` 文件由 SQL 线程来更新。文件的内容和执行 SHOW SLAVE STATUS 语句结果中相对应的字段值一样: Line Description 1 Relay_Log_File
  12. 12. 2 Relay_Log_Pos 3 Relay_Master_Log_File 4 Exec_Master_Log_Pos备份 slave 数据时,要把这两个文件也备份起来,和中继日志一道。想要恢复 slave 时就用得到它们了。如果丢失了中继日志,但是 `relay-log.info` 文件还存在,那么就可以判断出 SQL 线程执行了多少 master 二进制日志。然后执行 CHANGE MASTER TO 语句,带上 MASTER_LOG_FILE 和 MASTER_LOG_POS 选项告诉slave 要从 master 的二进制日志哪个位置重新读取。当然了,这要求 master 上相关的二进制日志都还留着。如果 slav 打算同步 LOAD DATA INFILE 语句,那么也要备份对应目录下的任何 `SQL_LOAD-*` 文件。这可以在 LOAD DATA INFILE 被中断后继续保持同步。这个目录由 --slave-load-tmpdir 选项来指定。默认地,如果没有指定的话,它的值就是变量 tmpdir 的值。6.4 设置同步以下描述了如何快速设置 MySQL 同步服务器。假设你打算同步全部的数据库,并且之前没有设置过。需要关闭master 服务器以完成全部的步骤。本章描述的过程可以用于一个 slave 的情况,也可以用于多个 slave 的情况。这只是一个最直接设置 slave 的办法,并不是只有一个。例如,已经有了 master 的数据快照(snapshot),master已经设置了服务器编号 ID(server_id)并且启用了二进制日志,这就无需关闭 master 或者阻止在 master 上更新数据了。详情请看"6.9 Replication FAQ"。
  13. 13. 想要完全掌握 MySQL 同步设置,最好把本章全部读完,并且测试在"14.6.1 SQL Statements for Controlling Master Servers"和"14.6.2 SQL Statements for Controlling Slave Servers"中提到的全部语句。而且要熟悉 各种同步设置选项,详情请看"6.8 Replication Startup Options"。 注意,这个过程以及后面一些同步 SQL 语句需要有 SUPER 权限。MySQL 4.0.2 以前,则是 PROCESS 权限。1. 请确认 master 和 slave 上都安装了较近的 MySQL 版本,且这些版本之间要能兼容,在"6.5 Replication Compatibility Between MySQL Versions"中列出来了。请确认在最新版本中还有存在问题,否则不要报告该 bug。2. 在 master 上新加一个帐户,slave 才能用它来连接。这个帐户必须授予 REPLICATION SLAVE 权限。如果 这个帐户只用于同步(推荐这么做),那就没必要授予其他权限了。设定你的域是 mydomain.com ,想要授权一 个帐户 repl 使用密码 slavepass ,允许它可以在域里的任何主机连接到 master 上。用 GRANT 语句来 创建帐户: 3. mysql> GRANT REPLICATION SLAVE ON *.* 4. -> TO repl@%.mydomain.com IDENTIFIED BY slavepass; 在 MySQL 4.0.2 以前,用 FILE 权限来代替 REPLICATION SLAVE : mysql> GRANT FILE ON *.* -> TO repl@%.mydomain.com IDENTIFIED BY slavepass; 如果打算在 slave 上执行 LOAD TABLE FROM MASTER 或 LOAD DATA FROM MASTER 语句,那 么必须给该帐户授予附加权限:
  14. 14. o 授予全局 SUPER 和 RELOAD 权限。o 授予对想要加载的所有表上的 SELECT 权限。在 master 上任何没有 SELECT 权限的表都会被 LOAD DATA FROM MASTER 略过。5. 如果只用到 MyISAM 表,执行 FLUSH TABLES WITH READ LOCK 语句刷新所有表并且阻止其他写 入: 6. mysql> FLUSH TABLES WITH READ LOCK; 不要退出执行 FLUSH TABLES 语句的客户端,以保持读锁有效(如果退出了,读锁就释放了)。然后从 master 上取得数据快照。比较简单的办法就是把数据目录打包压缩。例如,Unix 上的 tar , PowerArchiver , WinRAR , WinZip ,或 Windows 上的类似程序。想要用 tar 来创建一个压缩包,包 括所有的数据库,只需执行以下命令(把目录改成你的真实路径): shell> tar -cvf /tmp/mysql-snapshot.tar . 如果只想打包一个数据库 this_db ,只需执行命令: shell> tar -cvf /tmp/mysql-snapshot.tar ./this_db 然后把这个文件拷贝到 slave 的 `/tmp` 目录下。 slave 上,执行以下命令解开压缩包(把目录改成你的真实路 在 径): shell> tar -xvf /tmp/mysql-snapshot.tar
  15. 15. 可能不需要同步 mysql 数据库,因为在 slave 上的权限表和 master 不一样。这时,解开压缩包的时候要排除它。同时在压缩包中也不要包含任何日志文件,或者 `master.info~ 或 `relay-log.info` 文件。当在master 上的 FLUSH TABLES WITH READ LOCK 语句还生效时,在 master 上读取当前二进制文件的文件名及偏移位置: mysql > SHOW MASTER STATUS; +---------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +---------------+----------+--------------+------------------+ | mysql-bin.003 | 73 | test | manual,mysql | +---------------+----------+--------------+------------------+File 字段显示了二进制日志文件名,Position 字段显示了日志偏移位置。在这个例子中,日志文件是mysql-bin.003 ,偏移位置是 73 。记下这些值,在后面设置 slave 的时候就需要用到它们了。它们表示了slave 要从 master 的哪个偏移位置开始处理更新操作。取得快照和记录下日志名及偏移位置后,就可以让master 释放读锁了: mysql> UNLOCK TABLES;如果用到 InnoDB 表,那么最好使用 InnoDB Hot Backup 工具。它无需在 master 上请求任何锁就能做到快照的一致性,并且在后面中在 slave 上要用到的快照中已经记录了日志文件名以及偏移位置。InnoDBHot Backup 是费免费(商业的)的附加工具,它没有包含在 MySQL 发布包中。访问 InnoDB HotBackup 的主页 http://www.innodb.com/manual.php 查看更多详细信息。除去 InnoDB HotBackup 的另一个最快的办法就是关闭 master 服务器,拷贝 InnoDB 数据文件,日志文件,以及表结构定义文件(`.frm` 文件)。想要记录当前日志文件及偏移位置,需要在 master 关闭前执行如下可语句: mysql> FLUSH TABLES WITH READ LOCK;
  16. 16. mysql> SHOW MASTER STATUS; 尽快记下 SHOW MASTER STATUS 显示结果中的日志文件及偏移位置。然后,在不解锁的情况下关闭 master,确保 master 上的快照和记录的结果一致: shell> mysqladmin -u root shutdown 还有一个方法可以同时用于 MyISAM 和 InnoDB 表,这就是在 master 上作 SQL 转储而无需如上所述备份 二进制日志。 master 上运行 在 mysqldump --master-data 命令,然后把结果文件转储到 slave 上。不 过,这比拷贝二进制日志慢点。如果 master 在以前没有启用 --log-bin 选项,那么执行 SHOW MASTER STATUS 语句的结果中的文件名及偏移位置值为空了,那么后面在 slave 上指定的参数值就是空字符串( ) 和 4 了。7. 确认 master 上的 `my.cnf` 文件 [mysqld] 区间有 log-bin 选项。这个区间还必须有 server- id=master_id 选项,的值必须是 1 到 2^32-1 之间的正整数。例如: 8. [mysqld] 9. log-bin 10.server-id=1 如果这些配置选项不存在,那么就加上并且重启 master。11. 关闭要做 slave 的服务器,在 `my.cnf` 文件中增加如下选项: 12.[mysqld] 13.server-id=slave_id
  17. 17. slave_id 的值和 master_id 类似,是 1 到 2^32-1 之间的正整数。另外,这个 ID 必须不能和 master 的 ID 一样。例如: [mysqld] server-id=2 如果有多个 slave,那么每个 slave 都必须要有一个唯一的 server-id ,它的值不能和 master 以及其其他 slave 的值一样。可以把 server-id 想象成为 IP 地址:这些 ID 标识了整个同步组合中的每个服务器。如果没 有指定 server-id 的值,如果也没定义 master-host ,那么它的值就为 1,否则为 2。注意,如果没有 设定 server-id ,那么 master 就会拒绝所有的 slave 连接,同时 slave 也会拒绝连接到 master 上。因此, 省略配置 server-id 只对备份二进制日志有利。14. 如果已经备份了 master 上的数据(直接打包压缩的方式),那么在 slave 启动之前把它们拷贝过去。要确保文件的 权限属主等设置没问题。MySQL 运行的用户必须对这些文件有读写权限,就跟在 master 上一样。如果是用 mysqldump 备份的,那么可以直接启动 salve(直接跳到下一步)。15. 启动 slave,如果它之前已经运行同步了,那么在启动 slave 的时候使用 --skip-slave-start 选项使 之不会立刻去连接 master。最好也使用 --log-warnings 选项(从 MySQL 4.0.19 和 4.1.2 开始就是默 认启用了)来启动 slave,以知道发生问题时的更详细的信息(例如,网络或者连接问题)。从开始 MySQL 4.0.21 和 4.1.3,异常中止的连接不再记录到错误日志中,除非 --log-warnings 选项的值大于 1。16. 如果在 master 上用 mysqldump 备份数据的话,把文件导入 slave 中: 17.shell> mysql -u root -p < dump_file.sql18. 在 slave 上执行如下语句,把各个选项的值替换成真实值:
  18. 18. 19.mysql> CHANGE MASTER TO 20. -> MASTER_HOST=master_host_name, 21. -> MASTER_USER=replication_user_name, 22. -> MASTER_PASSWORD=replication_password, 23. -> MASTER_LOG_FILE=recorded_log_file_name, 24. -> MASTER_LOG_POS=recorded_log_position; 下表列出了各个选项字符串的最大长度: MASTER_HOST 60 MASTER_USER 16 MASTER_PASSWORD 32 MASTER_LOG_FILE 25525. 启动 slave 线程: mysql> START SLAVE; 做完上述过程后,slave 应该会连接到 master 上并且捕获所有从取得快照后的更新操作。 如果忘了设置 master 的 server-id 值,那么 slave 就不能连接到 master 上。 如果忘了设置 master 的 server-id 值,那么在错误日志中就会记录如下内容: Warning: You should set server-id to a non-0 value if master_host is set;
  19. 19. we force server id to 2, but this MySQL server will not act as a slave.如果因为其他原因不能同步的话,错误信息也会记录在 slave 的日志上。一旦 slave 开始同步了,就能在数据文件目录下找到 2 个文件 `master.info` 和`relay-log.info`。slave利用这 2 个文件来跟踪处理了多少 master 的二进制日志。不要删除或者修改这 2 个文件,除非知道怎么改。尽管如此,我们更推荐用 CHANGE MASTER TO 语句来做。注意:`master.info` 中的内容覆盖了部分命令行中指定的或 `my.cnf` 的选项。详情请看"6.8 ReplicationStartup Options"。只要有了 master 的数据快照,就可以按照上述几个步骤配置其它 slave 了。无需再次取得 master 的数据快照,每个 slave 都可以用这一份快照来做。6.5 不同 MySQL 版本之间的同步兼容性最早的二进制格式是在 MySQL 3.23 中开发出来的。在 MySQL 4.0 中改进了,MySQL 5.0 又改进了。在配置同步时需要升级服务器的话,它们之间的因果关系在"6.6 Upgrading a Replication Setup"中描述了。如果只关心同步,任何 MySQL 4.1.x 版本和 MySQL 4.0.x 是一样的,因为它们都使用相同格式的二进制日志。所以,这些版本是互相兼容的,它们之间可以无缝地运行同步。一个例外的情况是,MySQL 4.0.0 到 4.0.2 由于开发的较早,无法和后来的版本互相兼容,所以不要使用它们(它们是 4.0 版本的 alpha 系列。它们之间的兼容性在发布包的手册中均有相关文档)。
  20. 20. 下表展示了不同版本的 MySQL 之间的 master/slave 同步兼容性。 Master Master Master 3.23.33 and up 4.0.3 and up or any 4.1.x 5.0.0Slave 3.23.33 and up yes no noSlave 4.0.3 and up yes yes noSlave 5.0.0 yes yes yes一个通常的规则是,我们建议使用最近的 MySQL 版本,因为同步兼容性一直在改善。我们也建议 master 和 slave都使用同一个版本。6.6 升级同步如果升级服务器时涉及到配置同步,升级设置的步骤跟当前版本以及升级后的版本不同而异。6.6.1 升级同步到 4.0 或 4.1本节适用于从 MySQL 3.23 升级到 4.0 或者 4.1 的情况。4.0 的服务器必须是 4.0.3 或者更高,"6.5 ReplicationCompatibility Between MySQL Versions"中提到了。把 master 从 MySQL 3.23 升级到 4.0 或 4.1 时,首先要确认这个 master 的所有 slave 都已经是 4.0 或 4.1 了,否则的话,要先升级 slave:挨个关闭,升级,重启,重启同步等。
  21. 21. 通过以下步骤可以实现安全地升级,假定 master 要升级到 3.23,而 slave 已经是 4.0 或 4.1 了。注意,master 升 级后,不要重启使用任何旧的二进制日志的同步,因为它会干扰到 4.0 或 4.1 slave 的同步。1. 在 master 上执行 FLUSH TABLES WITH READ LOCK 语句,阻止所有的更新。2. 等到所有的 slave 都跟上了 master 的数据更新。在 master 上执行 SHOW MASTER STATUS 语句取得二进 制日志以及偏移位置。然后,再 slave 用这些值执行 SELECT MASTER_POS_WAIT() 语句,它会阻止 slave 上的同步且返回它已经同步的偏移位置。然后在 slave 上执行 STOP SLAVE 语句。3. 关闭 master,将它升级到 MySQL 4.0 或 4.1。4. 重启 master,记下它的新的二进制文件名。可以在 master 上执行 SHOW MASTER STATUS 语句来取得这 些信息。然后在每个 slave 上都执行如下语句: 5. mysql> CHANGE MASTER TO MASTER_LOG_FILE=binary_log_name, 6. -> MASTER_LOG_POS=4; mysql> START SLAVE; 6.6.2 升级同步到 5.0 本节适用于从 MySQL 3.23,4.0 或 4.1 升级到 5.0 的情况。4.0 的服务器必须是 4.0.3 或者更高,"6.5 Replication Compatibility Between MySQL Versions"中提到了。 首先,注意到 MySQL 5.0 还是 alpha 发布系列。它在各方面都比旧版本好(更容易升级一些同步中重要的会话变量, 例如 sql_mode ;详情请看"C.1.3 Changes in release 5.0.0 (22 Dec 2003: Alpha")。不过,它还没经过广 泛测试。由于是 alpha 版本,我们不建议用于任何生产环境(现在已经可以用于生产了,译者注)。
  22. 22. 把 master 从 MySQL 3.23,4.0 或 4.1 升级到 5.0.0 时,首先要确认这个 master 的所有 slave 都已经是 5.0.0 了,否则的话,要先升级 slave:挨个关闭,升级,重启,重启同步等。5.0.0 的 slave 可以读取升级前写入的执行 语句的中继日志。升级完后的 slave 创建的中继日志就是 5.0 格式了。 当所有的 slave 都升级完了,关闭 master,升级到 5.0.0,然后重启。5.0.0 的 master 也可以读取旧格式的二进 制日志。slave 能识别旧的格式并且合理处理它们。master 上新建的二进制日志都是 5.0.0 格式的。slave 也能识别 这格式。 换言之,在升级到 5.0.0 时无需特殊的规定,除非在升级 master 到 5.0.0 之前 slave 必须使用旧版本的。注意,把 5.0.0 降级到旧版本中不能自动地做了:必须确保所有的 5.0.0 格式二进制日志和中继日志都已经处理完了,然后 才能把它们删除完成降级。 6.7 同步特性及已知问题 以下列出了同步支持什么,不支持什么。附加的 InnoDB 特殊相关的信息以及同步请看"16.7.5 InnoDB and MySQL Replication"。• AUTO_INCREMENT , LAST_INSERT_ID() , 和 TIMESTAMP 的值都能被正常同步。• USER() , UUID() , 和 LOAD_FILE() 函数都完完全全地同步到 slave,因此可能不大可靠。MySQL 4.1.1 以前 的版本中的 CONNECTION_ID() 函数也是如此。 MySQL 4.1.1 及更高以后,新的 从 PASSWORD() 函数可以正 常同步,当然了,slave 必须是 4.1.1 或更高或者不同步它。如果有旧版本的 slave 必须要同步 PASSWORD() 函数, 那么 master 启动时必须增加 --old-password 选项,这样在 master 上就用旧的方法来实现 PASSWORD() 了(注意,MySQL 4.1.0 的 PASSWORD() 函数实现跟其他的版本都不同,最好不要同步 4.1.0)。
  23. 23. • 从 MySQL 4.0.14 开始同步 FOREIGN_KEY_CHECKS 变量。从 5.0.0 开始同步 sql_mode , UNIQUE_CHECKS ,和 SQL_AUTO_IS_NULL 变量。 SQL_SELECT_LIMIT 和 table_type 变量目前 还不能被同步。• 现在讨论使用不同字符集的 MySQL 服务器间同步的问题。 1. 首先,在 master 和 slave 上必须总是使用同样的全局字符集以及校验字符集(--default- character-set , --default-collation 都是相关的全局变量)。否则,slave 上可能会出现键重 复(duplicate-key)的错误,因为用 master 的字符集认为该键可能是唯一的,但是用 slave 的字符集则未必 然。 2. 第二,如果 master 必须低于 MySQL 4.1.3,则会话(session)的字符集必须和全局值一样(也就是说,不能 执行 SET NAMES , SET CHARACTER SET 等语句),因为这些对字符集的修改在 slave 不能识别。如 果 master 是 4.1.3 或者更高,slave 也是这样的话,那么会话字符集就可以随便修改了(执行 NAMES , CHARACTER SET , COLLATION_CLIENT , COLLATION_SERVER 等),并且这些修改都会被记录 到二进制日志中,然后同步到 slave 上,它就知道怎么做了。该会话还会阻止试图修改这些全局变量的操作; 就如前面所说,master 和 slave 必须使用同样的全局字符集。 3. 如果在 master 上有和全局变量 collation_server 不一样字符集的数据库,那么就要设计 CREATE TABLE 语句使得数据表不隐式地使用该数据库的默认字符集,因为这目前还是一个 bug(Bug #2326);一 个变通的办法是在 CREATE TABLE 语句中显式地声明数据表的字符集以及校验字符集。• 有时可能会把 master 上的事务表同步到 slave 后变成非事务表。例如,可以在 slave 上把 master 的 InnoDB 表当成 MyISAM 表。不过,slave 在一个 BEGIN/COMMIT 区块中停止的话就有问题了,因为 slave 会从 BEGIN 重新开 始。这个问题已经放到 TODO 中,很快会被修复。• 更新语句中如果用到了用户自定义变量(例如变量 @ var_name )的情况下,在 MySQL 3.23 和 4.0 不能被正确同步。 在 4.1 这已经修复了。注意,从 MySQL 5.0 开始,用户变量就不区分大小写了。在做 MySQL 5.0 和旧版本间的同步需 要考虑到这个问题。• 从 4.1.1 以及更高版本中,slave 可以用 SSL 方式连接到 master。
  24. 24. • 在 master 上执行的 CREATE TABLE 语句如果包括了 DATA DIRECTORY 或 INDEX DIRECTORY 子句, 那么它也会应用于 slave 上。如果 slave 上不存在对应的目录或者没有权限时便出现问题。 MySQL 4.0.15 开始,有个 从 sql_mode 选项叫 NO_DIR_IN_CREATE 。如果 slave 的 SQL 模式包含这个选项,那么它在同步 CREATE TABLE 语句前会忽略前面提到的 2 个子句。结果就是 MyISAM 的数据和索引文件都只能放在该表的数据库目录下。• 尽管没听说过发生过类似的情况,不过理论上确实存在这种可能性:如果一个查询被设计为非确定方式的修改数据,那 么可能导致 master 和 slave 的数据不一致。那么,就把决定的权力交给查询优化器吧。(通常这不是一个好的做法,甚至 超出了同步的范围,详情请看"1.8.7.3 Open Bugs and Design Deficiencies in MySQL")• 在 MySQL 4.1.1 之前,FLUSH , ANALYZE TABLE , OPTIMIZE TABLE ,和 REPAIR TABLE 语句没有写入 到二进制日志中,因此也不会同步到 slave 上。这通常不会引发问题,因为它们并没有修改数据。不过在特定情况下可能 导致问题。如果同步 mysql 数据库下的权限表,在更新时不是用 GRANT 语句,那么必须在 slave 上执行那么必须在 slave 上执行 FLUSH PRIVILEGES 语句才能使之生效。同样地,如果还有一个 MyISAM 表是 MERGE 表的一部 分,那么必须在 slave 上手工执行 FLUSH TABLES 语句。从 MySQL 4.1.1 开始,这些语句都写入二进制日志了(除 非指定选项 NO_WRITE_TO_BINLOG 或它的同名选项 LOCAL )。一些例外的情况是 FLUSH LOGS , FLUSH SLAVE , 和 FLUSH TABLES WITH READ LOCK (它们中的任何一个同步到 slave 的话都可能导致问题)。例子 可见"14.5.4.2 FLUSH Syntax"。• MySQL 只支持一个 master 多个 slave 的机制。以后我们会增加一个表决算法,如果当前 master 出现问题时能自动切 换。同时也会引进一个"代理"进程来帮助将 SELECT 查询发送到不同的 slave 上达到负载均衡。• 当服务器关闭,重启后,所有的 MEMORY (HEAP ) 表都清空了。从 MySQL 4.0.18 开始,master 用以下方式同步它 们:一旦 master 开始使用一个 MEMORY 表,它会在用完这些表之后在二进制日志中写入一个 DELETE FROM 语 句告诉 slave 把它们删除。详情请看"15.3 The MEMORY (HEAP ) Storage Engine"。• 除非关闭 slave(只是关闭 slave 线程),临时表也会同步;并且在 slave 上已经记录了一些还未被执行的需要用到临时表 的更新语句。关闭 slave 再重启后更新所需的临时表就不复存在了。为了避免这个问题,在有临时表时就不要关闭 slave。 或者,使用以下步骤: 1. 提交一个 STOP SLAVE 语句。
  25. 25. 2. 使用 SHOW STATUS 语句检查变量 Slave_open_temp_tables 的值。 3. 如果它的值是 0,运行 mysqladmin shutdown 命令关闭 slave。 4. 如果它的值不是 0,用 START SLAVE 语句重启 slave 线程。 5. 如果还有这样的好运气就再次执行同样的步骤吧。^_^ 我们会尽快解决这个问题。• 如果在一个循环 master/slave 同步关系中指定 --log-slave-updates 选项,那么就可以安全地连接到各个服 务器上。注意,很多语句可能在这种设置环境下不能正常工作,除非程序中已经特别注意避免这种更新时潜在的问题了, 因为可能在不同服务器上不同的顺序上发生更新问题。这意味着可以设定像下面的循环: • A -> B -> C -> A 服务器 ID 都已经编码到二进制日志中了,因此服务器 A 知道那些自己创建的日志,从而不会去执行它们(除非在服务器 A 上启动时增加 --replicate-same-server-id 选项,这个选项只在极少数情况下设置有意义)。因此,这就 不会存在无限循环了。不过这个循环只有在更新表时没有发生冲突才不会发生问题。换言之,如果在 A 和 C 中同时插入一 条记录,那么可能在 A 中不可能插入数据,因为它的键可能跟 C 的键冲突了。同样地,也不能在两个服务器上更新同一条 记录,除非 2 次更新操作间有足够的时间间隔。• 如果在 slave 上执行一个 SQL 语句后产生错误,那么 slave 的 SQL 线程就终止,然后它在错误日志中写入一条信息。可 以连接到 slave 上,解决问题(例如,不存在表)后,运行 START SLAVE 语句重启它。• 可以放心地关闭 master(干净地)之后再重启它。如果 slave 到 master 的连接断开了,它会立刻重连。如果失败了, slave 会定期重试(默认是每 60 秒重试一次,可通过 --master-connect-retry 选项来修改)。slave 也会处理 网络断开的情况。不过,slave 会在 slave_net_timeout 秒之后如果还没收到来自 master 的数据才会当作网络 断开的情况来处理。如果断开时间不长,可以减少 slave_net_timeout 的值。详情请看"5.2.3 Server System Variables"。
  26. 26. • 也可以放心地关闭 slave(干净地),它会记录停止的地方。不干净地关闭 slave 可能产生问题,特别是系统关闭了但缓存 还没刷新到磁盘时。可以提供不间断电源来提高系统容错性。master 的不干净关闭可能导致表和二进制内容的不一致;如 果是 InnoDB 表,使用 --innodb-safe-binlog 选项在 master 上就能避免这个问题。详情请看"5.9.4 The Binary Log"。• 由于 MyISAM 表的非事务本质,就可能发生一个语句只更新了部分表就返回错误代码的情况。例如,一个多重插入语句 中,有一条记录违反了约束键规则,一个更新语句在更新了一些记录后辈杀掉了。如果在 master 上发生这种情况了,那 么 slave 线程会推出,等待数据库管理员决定要怎么做,除非这个错误代码是合法的并且这个语句的执行结果也是一样 的错误代码。并没有关于错误代码是否合法的详细描述,一些错误代码可以用 --slave-skip-errors 选项屏蔽 掉。这个选项从 MySQL 3.23.47 开始就可以用了。• 如果把非事务表同步到事务表时在一个 BEGIN/COMMIT 段内更新数据表了,如果在非事务表提交之前有其他线程更 新它了,那么这个更新操作就不会正确地同步到二进制日志中。这是因为只有整个事务成功提交了才会写到二进制日志中。• 在 4.0.15 之前,任何在非事务表的更新操作会在它执行的时候立刻写入到二进制日志中,然而事务表的更新只有在 COMMIT 后才写入,ROLLBACK 的话就不写入了。因此在一些事务中更新事务表或非事务表时就需要考虑这个情况了 (不只是同步时会碰到这个问题,想要把二进制日志作为备份时也一样)。 MySQL 4.0.15 中,我们已经修改了更新事务 在 和非事务表混合的情况下的日志记录行为,它解决了这个问题(对于二进制日志来说顺序地记录语句是比较不错的做法, 所有必须的语句都会写进去,ROLLBACK 也一样)。当第二个连接更新非事务表而第一个连接的事务还没结束时,就会 有同样的问题了;仍会发记录语句顺序发生错误的问题,因为第二个连接会在更新完成后立刻写入到日志中。• 当 4.x 的 slave 从 3.23 的 master 上同步 LOAD DATA INFILE 时,SHOW SLAVE STATUS 中的 Exec_Master_Log_Pos 和 Relay_Log_Space 字段的值就不正确了。Exec_Master_Log_Pos 值 不正确的话在重启 slave 之后会导致问题;因此最好在重启前修改一下这个值,只需在 master 上运行 FLUSH LOGS 。这个 bug 在 MySQL 5.0.0 的 slave 中已经解决了。 下表列出了 MySQL 3.23 同步时会发生的问题,它们在 MySQL 4.0 已经解决了:• LOAD DATA INFILE 能正确处理,只要那个数据文件在更新开始时仍然存在于 master 上。
  27. 27. • LOAD DATA LOCAL INFILE 不再像以前 3.23 那样被略过了。• 在 3.23 中,RAND() 更新同步不正常。因此在使用 RAND() 更新时采用 RAND(some_non_rand_expr) 格式。例如,可以用 UNIX_TIMESTAMP() 作为 RAND() 的参数。 6.8 同步启动选项 不管是 master 还是 slave,都要设定 server-id 选项来确定使它们都有各自唯一的同步 ID。必须选择 1 到 2^32-1 之间的正整数。例如: server-id=3 。 关于 master 服务器上可用于控制二进制日志记录的选项详细描述请看"5.9.4 The Binary Log"。 下表描述了 slave 同步可用的选项,可以在命令行或者配置文件中设定它们。 一些 slave 同步选项以特定的方式来处理,在 slave 启动时,如果存在 `master.info` 文件并且包含这些选项, 那么 slave 将略过它们。这些选项如下:• --master-host• --master-user• --master-password• --master-port• --master-connect-retry
  28. 28. 从 MySQL 4.1.1 开始,一下选项也按照上述方式特殊处理:• --master-ssl• --master-ssl-ca• --master-ssl-capath• --master-ssl-cert• --master-ssl-cipher• --master-ssl-key 在 MySQL 4.1.1 中, `master.info` 文件的格式改变了以包含相应的 SSL 选项。另外,MySQL 4.1.1 文件格 式还包括了在第一行中的文件总行数。如果从旧版本升级到 4.1.1,那么服务器启动时会自动升级 `master.info` 为新的格式。不过,如果是从 4.1.1 降级到旧版本,就需要在系统第一次启动时手工删除文件的 第一行。注意,这种情况下,被降级的服务器就不能再使用 SSL 选项连接到 master 了。 slave 启动时如果不存在 `master.info` 文件,它就使用在命令行或者配置文件中指定的参数值来启动。这在每 次第一次启动 slave 服务器时都是这样,或者执行 RESET SLAVE 语句关闭且重启 slave 之后。 slave 启动时如果存在 `master.info` 文件,那么它就略过这些选项,而是直接读取 `master.info` 文件 中的值。 如果重启 salve 时使用的选项值和 `master.info` 中的不一样,那么这个新的值不会生效,因为 slave 服务器 还是照样只读取 `master.info` 文件。想要使用不同的选项值,可以在删除 `master.info` 后重启 slave 或 者使用 CHANGE MASTER TO 语句(推荐)重置选项值。
  29. 29. 假定在 `my.cnf` 设定了以下选项值: [mysqld] master-host=some_host第一次启动 slave 的时候,它从 `my.cnf` 中读取选项值,然后再把它们保存在 `master.info` 中。下次重启slave 时,它就只读取 `master.info` 的内容而略过 `my.cnf` 中的选项值了。企图修改 `my.cnf` 来改变同步选项是不可行的,不过可以通过执行 CHANGE MASTER TO 语句来实现:由于服务器认为 `master.info` 的优先级比配置文件高,因此建议根本不要在启动时附加同步选项,而只用CHANGE MASTER TO 语句。详情请看"14.6.2.1 CHANGE MASTER TO Syntax"。下例显示了一些配置 slave 的扩展选项: [mysqld] server-id=2 master-host=db-master.mycompany.com master-port=3306 master-user=pertinax master-password=freitag master-connect-retry=60 report-host=db-slave.mycompany.com
  30. 30. 下列所述启动选项都是用来控制同步的:它们中的大部分都可以在运行时用 CHANGE MASTER TO 语句来改变。 其他的,例如 --replicate-* ,只能在 salve 启动时指定。我们打算在将来解决这个问题。--log-slave-updates 通常,slave 从 master 接收更新操作后并没有再把它们记录在二进制日志中。这个选项告诉 slave 的 SQL 线程要 把这些更新操作记录在二进制日志中。想要这个选项起作用,需要同时启用 --log-bin 选项才能启用二进制 日志。在使用同步链机制时,就需要使用 --log-slave-updates 选项。例如,可能需要设置如下同步关 系: A -> B -> C 在这里,A 当作 B 的 master,B 当作 C 的 master。B 同时是 slave 又是 master,在 A 和 B 上都需要启用 --log-bin 选项,并且在 B 上还需要启用 --log-slave-updates 选项。 --log-warnings 让 slave 在执行同步时记录更多的错误日志。例如,它会通知你在网络/连接失败后重连成功,并且通知了每个 slave 线程如何启动的。这个选项在 MySQL 4.0.19 和 4.1.12 之后默认启用了;用 --skip-log- warnings 就可以禁用它。从 MySQL 4.0.21 和 MySQL 4.1.3 开始,除非这个选项的值大于 1,否则放弃的 连接不再记录在错误日志中。这个选项不只是用于限制同步,它产生的警告跨越了大部分操作。 --master-connect-retry= seconds 在 master 当机或者网络连接中断后,slave 在重新连接到 master 之前休眠的秒数。如果在 `master.info` 文件中存在,就优先使用它。如果没有设置,默认是 60。 --master-host= host
  31. 31. master 服务器的主机名或者 ip 地址。如果没有设置它,slave 线程无法启动。如果存在的话,`master.info`文件中选项值优先被读取。 --master-info-file= file_nameslave 记录 master 信息的文件名。默认名字是 `master.info`,放在数据文件目录下。 --master-password= password用于被授权连接到 master 上运行同步的帐户密码。如果存在的话,`master.info` 文件中选项值优先被读取。如果没有设置,就当作是空密码。 --master-port= port_numbermaster 上监听的 TCP/IP 端口号。如果存在的话,`master.info` 文件中选项值优先被读取。如果没有设置,就当作预编译的设置。如果没有修改 configure 选项参数,那么就是 3306。 --master-ssl,--master-ssl-ca= file_name, --master-ssl- capath= directory_name, --master-ssl-cert= file_name, --master-ssl- cipher= cipher_list, --master-ssl-key= file_name用于设定用 SSL 安全连接到 master 的选项。它们的意义对应于"5.6.7.5 SSL Command-Line Options"中提到的 --ssl , --ssl-ca , --ssl-capath , --ssl-cert , --ssl-cipher , --ssl-key 选项。如果存在的话,`master.info` 文件中选项值优先被读取。这些选项是从 MySQL 4.1.1 之后开始可以用的。 --master-user= username用于被授权连接到 master 上运行同步的帐户。这个帐户必须有 REPLICATION SLAVE 权限(在 MySQL4.0.2 以前,则是 FILE 权限)。如果存在的话,`master.info` 文件中选项值优先被读取。如果没有设置,就当作是 test 。 --max-relay-log-size= #
  32. 32. 中继日志自动轮转(rotate)的大小。详情请看"5.2.3 Server System Variables"。这个选项是从 MySQL 4.0.14之后才可以用的。 --read-only这个选项令 slave 除了 slave 线程或者拥有 SUPER 权限用户之外的都不能更新数据。这能确保 slave 不会接受来自其他客户端的更新。这个选项是从 MySQL 4.0.14 开始有的。 --relay-log= file_name中继日志的名字。默认名字是 host_name -relay-bin. nnn ,host_name 是 slave 服务器的主机名,nnn 是指中继日志的顺序号。可以用这个选项创建不依赖主机名的中继日志,或者在中继日志越来越大(不想降低max_relay_log_size 的值)且需要将它们放在非数据文件目录下,或者想使用磁盘间的负载均衡来提高速度等情况。 --relay-log-index= file_name中继日志索引文件的位置及文件名。它的默认值是 host_name -relay-bin.index ,host_name 是slave 服务器主机名。 --relay-log-info-file= file_nameslave 上记录中继日志信息的文件名。默认是数据文件目录下的`relay-log.info`。 --relay-log-purge={0|1}在不需要中继日志时禁用或启用自动清除。默认值是 1(启用)。这是一个全局变量,可以用 SET GLOBALrelay_log_purge 来动态更改。这个选项从 MySQL 4.1.1 开始可以用。 --relay-log-space-limit= #用于加大 slave 上中继日志的总大小(如果值为 0 表示"无限")。这在 slave 主机只有有限的空间时很有用。当达到这个限制后,I/O 线程直到 SQL 线程删除一些无用的中继日志后才会继续从 master 读取二进制日志事件。注意,这个限制不是绝对的:在删除中继日志之前,SQL 线程可能还需要更多的二进制日志事件。这种情况下,I/O 线程会超越这个限制,直到 SQL 线程删除一些中继日志,因为如果不这么做的话就会导致死锁(在 MySQL 4.0.13 之
  33. 33. 前就是这样)。不要设置 --relay-log-space-limit 的值小于 2 倍 --max-relay-log-size(如果 --max-relay-log-size 的值为 0,则是 --max-binlog-size ) 的值。在这种情况下,由于已经超过 --relay-log-space-limit 了,I/O 线程需要等待更多的剩余空间,但是 SQL 线程没有可以删除的中继日志来满足 I/O 线程的需求。这就会强制 I/O 线程暂时忽略 --relay-log-space-limit 限制。 --replicate-do-db= db_name告诉 slave 只同步那些缺省数据库是 db_name (也就是用 USE 选中的)的语句。想要指定更多的数据库,只需多次使用该选项,每次指定一个数据库。注意,类似 UPDATE some_db.some_table SETfoo=bar 这样的跨库操作语句以及没有选中数据库的操作都不会被同步。如果必须使用跨库操作,要确保使用 MySQL 3.23.28 或更高,并且使用 --replicate-wild-do-table= db_name .% 选项。请仔细阅读最后面的注意事项。下面是一个不能按照预期工作的例子:如果启动 slave 时使用 --replicate-do-db=sales 选项,并且在 master 上执行下列语句,那么这个 UPDATE 语句不会被同步: USE prices; UPDATE sales.january SET amount=amount+1000;如果需要同步跨库操作,只需使用 --replicate-wild-do-table= db_name .% 选项。这个"只检查缺省数据库"特性的主要原因是因为想要单从一个语句中判断是否要被同步比较困难(例如,使用多表 DELETE或者 UPDATE ,这就跨库了)。不过想要检查是否是缺省数据库却很快。 --replicate-do- table= db_name.tbl_nam e
  34. 34. 告诉 slave 只同步那些指定的数据表。想要指定更多的数据表,只需多次使用该选项,每次指定一个数据表。这个选项支持跨库更新,和 --replicate-do-db 选项相反。请仔细阅读最后面的注意事项。 --replicate- ignore-db= db_name告诉 slave 不要同步那些缺省数据库是 db_name (也就是用 USE 选中的)的语句。想要指定更多的数据库,只需多次使用该选项,每次指定一个数据库。如果有跨库操作且希望这些操作要被同步就不要使用该选项。请仔细阅读最后面的注意事项。下面是一个不能按照预期工作的例子:如果启动 slave 时使用 --replicate-ignore-db=sales 选项,并且在 master 上执行下列语句,那么这个 UPDATE 语句不会被同步: USE prices; UPDATE sales.january SET amount=amount+1000;想要让跨库操作能正常同步,只需使用 --replicate-wild-ignore-table= db_name .% 选项。 -- replicate- ignore- table= db_n ame.tbl_na me告诉 slave 不要同步指定数据表的任何更新语句(甚至用同一个语句更新的其他表)。想要指定更多的数据表,只需多次使用该选项,每次指定一个数据表。这个选项支持跨库更新,和 --replicate-ignore-db 选项相反。请仔细阅读最后面的注意事项。
  35. 35. -- replicat e-wild- do- table= db _name.tb l_name限制 slave 只同步那些匹配指定模式的数据表。模式中可以包含通配符 `%` 和 `_`,它们的含义和 LIKE 模式一样。想要指定更多的数据表,只需多次使用该选项,每次指定一个数据表。请仔细阅读最后面的注意事项。例如: --replicate-wild-do-table=foo%.bar% 会同步所有以 foo 开头的数据库下的以bar 开头的数据表上的更新操作。如果匹配模式是 % ,则匹配所有的表名,且应用到数据库级语句(CREATE DATABASE , DROPDATABASE ,和 ALTER DATABASE )。例如,使用 --replicate-wild-do-table=foo%.% 选项的话,所有匹配 foo% 模式的数据库级操作都会被同步。如果想要在数据库/表模式中包含原义通配符,需要用反斜杠来转义它们。例如,想要同步 my_own%db 数据库下的所有表,但是不想同步 my1ownAABCdb 数据库下的表,就需要转义字符 `_`: --replicate-wild-do-table=my_own%db 。如果是在命令行中使用这个选项,就可能需要两个反斜杠来转义,这依赖于命令行解释器。例如,在 bash shell 下,就需要输入: --replicate-wild-do-table=my_own%db 。 -- re pl ic at e-
  36. 36. wi ld - ig no re - ta bl e= db _n am e. tb l_ na me限制 slave 不同步那些匹配指定模式的数据表。想要指定更多的数据表,只需多次使用该选项,每次指定一个数据表。请仔细阅读最后面的注意事项。例如,--replicate-wild-ignore-table=foo%.bar% 就不会同步所有以 foo 开头的数据库下的以 bar 开头的数据表上的更新操作。想要了解匹配模式如何工作的,请查看 --replicate-wild-ignore-table 选项的具体描述。模式中包含原义通配符的规则和 --replicate-wild-ignore-table 选项一样。 -- replicate
  37. 37. -rewrite- db= from_n ame - > to_name告诉 slave 把在 master 上的缺省数据库 from_name (只有用 USE 选中的)转换成 to_name 。只有涉及到数据表的语句(不包括类似 CREATE DATABASE , DROP DATABASE ,和 ALTER DATABASE )才会被同步,并且只针对 master 上缺省数据库为 from_name 的情况。这个选项不支持跨库操作。注意,数据库名字转换先于 --replicate-* 规则之前测试。如果是在命令行中使用这个选项,需要把 `> 字符用引号引用起来。例如: shell> mysqld --replicate-rewrite-db="olddb->newdb" --replica same-serv id该选项用于 slave 之上。通常使用它的默认值 0,用于避免无限同步循环。如果设置为 1,那么 slave 就不会忽略那些跟它有同样服务器编号的更新日志了;通常它只用于比较罕见的配置中。如果启用 --log-slave-updates 选项,则不能设置为 1。注意,从 MySQL 4.1 开始,slave 的 I/O 线程默认不把包含 slave 的服务器编号的二进制日志写到中继日志中(相对 4.0 这能节省磁盘使用)。因此想要在 4.1 中使用 --replicate-same-server-id 选项,在 slave 读取自己的更新事件让 SQL 线程来执行之前要确保启动 slave 时使用该选项。 --report- host= host在 salve 注册时要报告的 master 主机名或 IP 地址。在 master 上执行 SHOW SLAVE HOSTS 语句时就会显示出来了。如果不想 slave 注册到 master 就无需设置这个选项。注意,这在 slave 连接到 master 之后,只根据这
  38. 38. 个配置 master 还不能直接从 TCP/IP 套接字中读取 slave 的 IP 地址。因为存在 NAT 或者其他路由机制,这个IP 信息还不足以在 master 或者其他主机上连接到 slave 上。这个选项是从 MySQL 4.0.0 开始可以用的。 --report- port= port连接到 slave 的 TCP/IP 端口,在 slave 注册到 master 时用的到。除非 slave 在非默认端口上监听或者从master 或其他客户端上到连接到 slave 使用的是特定的隧道,否则无需设置这个值。如果不确定,就不要设置它。这个选项是从 MySQL 4.0.0 开始可以用的。 --skip-sl告诉 slave 服务器在启动时不要运行 slave 线程。只需使用 START SLAVE 语句来启动 slave 线程。 -- slave_com col={0|1}如果它设置为 1,并且 maste/slave 都支持的话,就采用压缩协议传输数据。 --slave-l tmpdir= fislave 创建临时文件的目录。这个选项值默认地和系统变量 tmpdir 的值一样。slave 的 SQL 线程同步 LOADDATA INFILE 语句时,它从中继日志中提取出要被加载的文件放到临时文件中,然后把它们加载到 slave 中。如果在 master 上加载的文件很大,那么 slave 上的临时文件也会很大。因此建议在 slave 上指定这个选项时把它放在剩余空间比较多的文件系统上。这是,最好也指定 --relay-log 到那个文件系统中,因为中继日志可能也会很大。--slave-load-tmpdir 必须指向基于磁盘的文件系统,而不能是基于内存的文件系统:slave可能会在机器重启后同步 LOAD DATA INFILE 语句时需要用到这个临时文件。这个目录同样不能在会被操作系统的启动进程清除的目录下。 --slave-n
  39. 39. salve 放弃读之后等待多少秒再次从 master 读取更多的数据,考虑到了连接断开,尝试重连的情况。第一次重试 会在超时后立刻执行。重试的时间间隔由选项 --master-connect-retry 控制。 --slave-s [ err_code all] 通常,发生错误时同步就会停止,以提供手工解决数据不一致的情况。这个选项告诉 slave 的 SQL 线程当执行语 句时返回的错误代码在该列表中时继续运行。 除非真正的理解了为什么会产生相应的错误后,否则不要设置这个选项。如果同步设置以及客户端程序都没有 bug,并且也不是 MySQL 自身的 bug 的话,那么就不会出现让同步停止的错误了。不加区分地使用这个选项,会 导致 slave 无可救药地背离 master 的同步,并且你也不知道这是为什么。 可以在从 slave 的错误日志并且在 slave 上执行 SHOW SLAVE STATUS 语句的结果中就能看到错误代码了。 服务器错误代码详情请看"22 Error Handling in MySQL"。 你也可以(最好不要)使用非常不推荐使用的值 all ,它能忽略所有的错误信息,不管什么情况都继续保持同步。 不消说,如果使用这个选项值,就不可能期待有数据的完整性了。这种情况下,就不能抱怨 slave 的数据无论在哪 个地方都和 master 不接近了。已经警告过你了。例如: --slave-skip-errors=1062,1053 --slave-skip-errors=all --replicate-* 模式根据以下规则来决定一个语句是要执行还是被忽略:1. 是否有 --replicate-do-db 或 --replicate-ignore-db 规则?
  40. 40. o 是:测试 --binlog-do-db 和 --binlog-ignore-db 选项(详情请看"5.9.4 The Binary Log")。测试结果?  忽略:忽略并且退出。  执行:不立刻执行,推迟判断,到下一步。o 否:到下一步。2. 是否有 --replicate-*-table 规则?o 否:执行并且退出。o 是:走到下一步。只有要被更新的表才和这个规则作比较(INSERT INTO sales SELECT * FROM prices :中只有 sales 和规则比较)。如果有好几个表一起被更新(多表语句),第一个匹配的表(匹配 `do` 或 `ignore`)胜出。也就是说,只有第一个表和规则作比较。然后,如果还没有产生任何决定,就比较第二个表, 以此类推。3. 是否有 --replicate-do-table 规则?o 是:这个表是否匹配这些规则?  是:执行并且退出。  否:走到下一步。
  41. 41. o 否:走到下一步。4. 是否有 --replicate-ignore-table 规则?o 是:这个表是否匹配这些规则?  是:忽略并且退出。  否:走到下一步。o 否:走到下一步。5. 是否有 --replicate-wild-do-table 规则?o 是:这个表是否匹配这些规则?  是:执行并且退出。  否:走到下一步。o 否:走到下一步。
  42. 42. 6. 是否有 --replicate-wild-ignore-table 规则?o 是:这个表是否匹配这些规则?  是:忽略并且退出。  否:走到下一步。o 否:走到下一步。7. 没有匹配 --replicate-*-table 规则。是否有其他表匹配这些规则?o 是:循环查找匹配。o 否:已经测试所有要被更新的表且找不到任何匹配规则。是否有 --replicate-do-table 或 --replicate-wild-do-table 规则?  是:忽略并且退出。  否:执行并且退出。 6.9 同步 FAQ 问: master 还在运行中,如何在不停止它的情况下配置 slave?
  43. 43. 答: 需要设计几个选项参数。如果已经有了 master 的备份并且记录了数据快照二进制日志文件名以及偏移位置(运 行 SHOW MASTER STATUS 查看结果),执行以下步骤:1. 确定 slave 指定了一个唯一的服务器编号。2. 在 slave 上执行如下语句,把一些选项值改成实际值: 3. mysql> CHANGE MASTER TO 4. -> MASTER_HOST=master_host_name, 5. -> MASTER_USER=master_user_name, 6. -> MASTER_PASSWORD=master_pass, 7. -> MASTER_LOG_FILE=recorded_log_file_name, -> MASTER_LOG_POS=recorded_log_position;8. 在 slave 上执行 START SLAVE 语句。 如果事先没有备份 master 的数据,可以用以下方法快速创建一个备份。以下所有的操作都是在 master 上。1. 提交语句: 2. mysql> FLUSH TABLES WITH READ LOCK;3. 确保这个锁一直存在,执行以下命令(或者其他类似的):
  44. 44. 4. shell> tar zcf /tmp/backup.tar.gz /var/lib/mysql5. 执行以下语句,记录下输出的结果,后面要用到: 6. mysql> SHOW MASTER STATUS;7. 释放锁: mysql> UNLOCK TABLES; 上述步骤的另一个办法是创建 master 的 SQL 转储文件。只需在 master 上执行 mysqldump --master- data 命令,然后将导出来的 SQL 转储文件载入 slave。不过,这么做会制作二进制数据快照的方式慢一点。 无论使用上述两种方法的哪种,最后都能创建 master 的数据快照然后记录二进制日志文件名以及偏移位置。可以在 好几的其他的 slave 上使用同一个备份的二进制数据快照。得到 master 的快照后,只要 master 的二进制日志完好 无损,接着就能开始设置 slave 了。两个决定是否需要等待较长时间的限制是:在 master 上磁盘空间保存二进制日 志,以及 slave 从 master 抓取更新事件。 也可以使用 LOAD DATA FROM MASTER 。这个语句可以很方便地在 slave 上取得数据快照并且能立刻调整二 进制日志文件名以及偏移位置。在将来,我们推荐用 LOAD DATA FROM MASTER 来设置 slave。警告,它只 能用于 MyISAM 表,并且可能会保持一个较长时间的读锁。由于它还没达到所期望的高效率,因此如果数据表很 大,最好还是在执行完 FLUSH TABLES WITH READ LOCK 后直接制作二进制数据快照。 问:是否 slave 总是需要连接到 master?
  45. 45. 答:不,非必需。slave 可以好几小时甚至几天关闭或者不连接 master,然后重连再取得更新操作日志。例如,可以在拨号链接上设置一个 mater/slave 关系,拨号可能只是零星的不定期的连接。这种做法隐含的是,在任何指定的时间里,除非使用特殊的度量标准,否则 slave 不能保证总是能和 master 保持同步。在未来,有个选项可以阻止master,除非至少有一个 slave 在同步中。问:怎么知道比 master 晚了多少?也就是说,怎么知道 slave 最后同步的时间?答:如果 slave 是 4.1.1 或者更高,只需查看 SHOW SLAVE STATUS 结果中的Seconds_Behind_Master 字段。对于老版本,可以用以下办法。如果在 slave 上执行 SHOWPROCESSLIST 语句结果显示 SQL 线程(对 MySQL 3.23 则是 slave 线程)正在运行,这就意味着该线程至少从master 读取一个更新操作事件。详情请看"6.3 Replication Implementation Details"。当 SQL 线程执行一个 master 上读取的更新操作事件时,它把自己的时间改成事件的时间(这也就是TIMESTAMP 也要同步的原因)。在SHOW PROCESSLIST 结果中的 Time 字段中,slave 的 SQL 线程显示的秒数就是最后一次同步的时间戳和slave 本机的实际时间相差秒数。可以根据这个值来判断最后同步的时间。注意,如果 slave 已经从 master 断开好几个小时了,然后重新连接,就能看到 slave 的SHOW PROCESSLIST 结果中的 SQL 线程的 Time 字段的值类似 3600。这是因为 slave 正在执行一个小时前的语句。问:如何强制 master 在 slave 赶上全部更新之前阻止更新操作?答:执行以下步骤:
  46. 46. 1. 在 master 上,执行以下语句: 2. mysql> FLUSH TABLES WITH READ LOCK; mysql> SHOW MASTER STATUS; 记录下结果中的日志文件名以及偏移位置,它们是同步的坐标值。3. 在 slave 上,提交以下语句,MASTER_POS_WAIT() 函数的参数的值就是前面取得的同步坐标值: 4. mysql> SELECT MASTER_POS_WAIT(log_name, log_offset); SELECT 语句会阻止更新,直到 slave 同步到了上述日志文件及位置。在这个时候,slave 就和 master 保持同 步了,并且这个语句就会返回。5. 在 master 上,执行以下语句允许 master 重新处理更新操作: mysql> UNLOCK TABLES; 问:设置一个双向复制时要注意什么问题? 答:MySQL 同步目前还不支持任何在 master 和 slave 上的分布式(跨服务器)更新锁协议以保证操作的原子性。也 就是说,存在这样的可能性:客户端 A 在并存的 master 1 上做了一个更新,同时,在它同步到并存 master 2 上 之前,客户端 B 在 master 2 上可能也做了一个和客户端 A 在 master 1 上不同的更新操作。因此,当客户端 A 所做 的更新同步到 master 2 时,它将产生和 master 1 上不同的数据表,尽管 master 2 上的更新操作也全都同步到
  47. 47. master 1 上去。这意味着除非能确保所有的更新都能以任何顺序安全地执行,否则不要使用双向同步,或者除非注意在客户端程序中的不知原因的无序更新操作。同时也要意识到在所关心的更新问题上,双向同步实际上并不能很大地改善性能(甚至没有)。两个服务器都需要执行同样数量的更新操作,在一台服务器上也是。唯一区别的是,可能这样做会减少一些锁争夺,因为来自其他服务器的更新操作都会被串行地放到 slave 线程中。甚至这种好处还可以作为网络延迟的补偿。问:我如何利用同步来提高系统性能?答:需要安装一个服务器作为 master 并且把所有的写操作直接放在这上面。然后配置多个廉价的使用机架磁盘的slave,把读操作分配给 master 和 slave。还可以在启动 slave 时使用 --skip-innodb , --skip-bdb ,--low-priority-updates ,和 --delay-key-write=ALL 选项来提高 slave 端的性能。这种情况下,slave 会使用非事务的 MyISAM 表来代替 InnoDB 和 BDB 表,已取得更快速度。问:如何准备客户端应用程序的代码来适应同步应用?答:如果代码中负责存取数据库的部分已经被合理地抽象化/模块化了,将它们转化成适用运行于同步环境中将会很平滑和简单。只需要修改数据库存取实现部分,把所有的写操作放到 master 上,把所有的读操作放到 master 或者slave 上。如果你的代码还没达到这个层次的抽象化,那么这将成为整理代码的机会和动机。可以使用类似以下函数创建封装类库或者模块:
  48. 48. • safe_writer_connect()• safe_reader_connect()• safe_reader_statement()• safe_writer_statement() 每个函数名的 safe_ 表示它们会处理所有的错误情况。可以使用其他函数名。重要的是,要为读连接、写连接、读、 写定义好统一的接口。 然后将客户端代码转换成使用封装的类库。已开始可能是很痛苦且麻烦的,不过在将来长期运行中就能得到回报了。 所有使用上述方法的应用程序都会在 master/slave 配置中有优势,即使包含多个 slave。这些代码将很容易维护, 一些额外的麻烦也会很少。自豪需要修改一个或者两个函数;例如,想要记录每个语句执行了多长时间,或者在上千 个语句中哪个出现错误了。 如果已经写了很多代码,你可能想要自动转换它们,那么可以使用 MySQL 发布的 replace 工具,或者自己写 转换脚本。理想地,你的代码已经使用了统一的编程风格。如果不是,最好重写它们,或者可以遍历检查一下,手工 规范化一下代码风格。 问:MySQL 同步何时且有多少能提高系统性能?
  49. 49. 答:MySQL 同步对于频繁读但不频繁写的系统很有好处。理论上来讲,使用单一 master/多 slave 的配置,就可以通过这个方法来衡量系统:增加更多的 slave 直到用完所有的网络带宽或者 master 的更新操作增长到了不能再处理的点了。想要知道增加多少个 slave 之后得到的性能才能平稳,以及能提高多少性能,就需要知道查询模式,并且根据经验对典型的 master 和 slave 做读(每秒读或 max_reads )和写(max_write )基准测试得到它们之间的关系。下例展示了一个理想系统取得的性能的简单计算方法。设定系统负载由 10%写和 90%读组成,我们已经通过基准测试确定 max_reads 是 1200 - 2 *max_writes 。换句话说,系统可以达到每秒做没有写的 1200 次读操作,写操作平均是读操作的 2 倍慢,它们之间的关系是线性的。让我们假设 master 和每个 slave 都有同样的容量,有一个 master 和 N 个 slave。每个服务器(master 或 slave):reads = 1200 - 2 * writesreads = 9 * writes / (N + 1) (读是分开的,但是所有写是在所有的服务器上的)9 * writes / (N + 1) + 2 * writes = 1200
  50. 50. writes = 1200 / (2 + 9/(N+1)) 最后的等式说明了 N 个 slave 的最大写数量,给它每分钟的最高读频率 1200 和 1 次写 9 次读的机率。 分析结论比率如下:• 如果 N = 0(意味着没有同步),系统大致可以处理每秒 1200/11 = 109 次写。• 如果 N = 1,增加到每秒 184 次写。• 如果 N = 8,增加到每秒 400 次写。• 如果 N = 17,增加到每秒 480 次写。• 最终,随着 N 接近无穷大(我们的预算为负无穷大),则可以达到几乎每秒 600 次写,大约提高系统吞吐量 5.5 倍。尽管 如此,当有 8 台服务器时,已经提高了 4 倍了。 注意,上面的计算是假设了网络带宽无穷大,并且忽略了一些系统中比较大的因素。在很多情况下,当系统增加 N 个同步 slave 之后,是无法精确计算出上述预计结果的。不过,先看看下列问题将有助于你知道是否有和有多少系统 性能上的改善:• 系统读/写得比率是多少?• 减少读操作后一个服务器能增加处理多少写操作?• 你的网络带宽足够给多少 slave 使用?
  51. 51. 问:如何利用同步提供冗余/高可用性? 答:使用当前已经可用的特性,可以配置一个 master 和一个(或多个)slave,并且写一个脚本监控 master 是否运 行着。然后通知应用程序和 slave 在发现错误时修改 master。一些建议如下:• 使用 CHANGE MASTER TO 语句告诉 slave 修改 master。• 一个让应用程序定位 master 所在主机的办法就是给 master 使用动态 DNS。例如 bind 就可以用 `nsupdate` 来动态 更新 DNS。• 使用 --log-bin 选项,不使用 --log-slave-updates 选项来启动 slave。这样就能让 slave 运行 STOP SLAVE ; RESET MASTER 语句 后随时准备变成 master,并且在其他 slave 上运行 CHANGE MASTER TO 。例如,有以下配置方案: • WC • • v • WC----> M • / | • / | • v v v • S1 S2 S3
  52. 52. M 表示 masetr,S 表示 slave,WC 表示提交读写操作的客户端;只提交读操作的客户端没有表示出来,因为它们无需切换。S1,S2,S3 都是使用--log-bin 选项,不用 --log-slave-updates 选项运行的 slave。由于除非指定 --log-slave-updates 参数,否则从 master 读到的更新操作都不会记录到二进制日志中,因此每个 slave 上的二进制日志都是空的。如果因为某些原因 M 不能用了,可以指定一个 slave 作为 master。例如,如果指定 S1,则所有的 WC 都要重定向到 S1 上,S2 和 S3 都需要从 S1 上同步。确定所有的 slave 都已经处理完各自的中继日志了。在每个 slave 上,提交 STOP SLAVE IO_THREAD 语句,然后检查 SHOW PROCESSLIST 的结果直到看到 Has read all relay log 了。当所有的 slave 都这样子之后,就可以按照新的方案设置了。在 slave S1 上提交STOP SLAVE 和 RESET MASTER 语句将其提升为 master。在其他 slave S2 和 S3 上,提交 STOP SLAVE 和 CHANGE MASTERTO MASTER_HOST=S1 ( S1 代表 S1 的真实主机名) 语句修改 master。把 S2,S3 如何连接到 S1 的参数(用户,密码,端口等)都附加到 CHANGE MASTER 后面。在CHANGE MASTER 中无需指定 S1 的二进制日志文件名和偏移位置:因为 CHANGE MASTER 默认就是第一个二进制日志和偏移位置 4。最后,在 S2 和 S3 上提交 START SLAVE 语句。然后让所有的 WC 都把他们的语句重定向到 S1 上。从这个时候开始,从所有的 WC 发送到 S1 上的更新语句都会写到 S1的二进制日志中,它们包含了从 M 死掉之后发送到 S1 的全部更新语句。配置结果如下: WC / | WC | M(unavailable)
  53. 53. | | v v S1<--S2 S3 ^ | +-------+ 当 M 又起来了之后,只需在 M 上提交和在 S2 和 S3 上的一样的 CHANGE MASTER 语句,将它变成一个 slave 并且 读取自从它死掉之后的全部 WC 提交的更新操作。想要把 M 重新变成 master(例如因为它的性能更好),就执行类似上面 的操作,把 S1 当作失效了,把 M 提升为新的 master。在这个步骤中,别忘了在把 S2 和 S3 修改成为 M 的 slave 之前在 M 上运行 RESET MASTER 语句。否则的话,它们会从 M 开始失效的那个时刻开始读取 WC 提交的更新操作日志。 现在我们就运行着一个完整的自动选择 master 的 MySQL 同步系统,不过在它准备好之前,需要创建自己的监控 工具。 6.10 同步疑难解答 如果按照上述步骤设定好同步之后,它不能正常工作的话,首先检查以下内容:• 查看一下错入日志信息。不少用户都在这方面做得不够好以至于浪费时间。• master 是否在记录二进制日志?用 SHOW MASTER STATUS 检查一下状态。如果是,Position 的值不为零; 否则,确定 master 上使用了 log-bin 和 server-id 选项。• slave 是否运行着?运行 SHOW SLAVE STATUS 语句检查
  54. 54. Slave_IO_Running 和 Slave_SQL_Running 的值是否都是。如果不是,确定是否用同步参数启动 slave 服务器了。• 如果 slave 正在运行,它是否建立了到 master 的连接?运行 SHOW PROCESSLIST 语句检查 I/O 和 SQL 线程的 State 字段值。详情请看"6.3 Replication Implementation Details"。如果 I/O 线程状态为 Connecting to master ,就检查一下 master 上同步用户的权限是否正确, master 的主机名,DNS 设置,master 是否确实正在运行着,以及 slave 是否可连接到 master,等等。• 如果 slave 以前运行着,但是现在停止了,原因通常是一些语句在 master 上能成功但在 slave 上却失败了。如果 salve 已经取得了 master 的全部快照,并且除了 slave 线程之外不会修改他的数据,那么应该不会发生这样的情形。如果确实 发生了,那么可能是一个 bug 或者你碰到了"6.7 Replication Features and Known Problems"中提到的同步限制之 一。如果是一个 bug,那么请按照"6.11 Reporting Replication Bugs"的说明报告它。• 如果一个语句在 master 上成功了,但是在 slave 上却失败了,并且这时不能做一次完整的数据库再同步(也就是删除 slave 上的数据,重新拷贝 master 的快照),那么试一下: 1. 判断 slave 的数据表是否和 master 的不一样。试着找到怎么会发生这种情况,然后将 slave 的表同步成和 master 一样之后运行 START SLAVE 。 2. 如果上述步骤不生效或者没有执行,试着这个语句是否能被手工安全地运行(如果有必要),然后忽略 master 的下一个语句。 3. 如果决定要忽略 master 的下一个语句,只需在 slave 上提交以下语句: 4. mysql> SET GLOBAL SQL_SLAVE_SKIP_COUNTER = n; mysql> START SLAVE; 如果下一个语句没有使用 AUTO_INCREMENT 或 LAST_INSERT_ID() ,那么 n 的值应为为 1 。否 则,它的值为 2 。设定为 2 是因为 AUTO_INCREMENT 或 LAST_INSERT_ID() 在 master 的二进 制日志中占用了 2 条日志。
  55. 55. 5. 如果确定 slave 精确地同步 master 了,并且没有除了 slave 线程之外的对数据表的更新操作,则推断这是因 为 bug 产生的差异。如果是使用最近的版本,请报告这个问题,如果使用的是旧版本,试着升级一下。 6.11 报告同步 Bugs 当确定没有包含用户的错误,并且同步还是不能正常工作或者不稳定,就可以报告 bug 了。我们需要你尽量多的跟 踪 bug 的信息。请花点时间和努力准备一个好的 bug 报告。 如果有一个演示 bug 的可重现测试案例的话,请进入我们的 bug 数据库 http://bugs.mysql.com/。如果碰到一个 幽灵般的问题(不可重现),请按照如下步骤:1. 确定没有包含用户错误。例如,在 slave 线程以外更新 slave 的数据,那么数据就会不能保持同步,也可能会导致 违反更新时的唯一键问题。这是外部干涉导致同步失败的问题。2. 使用 --log-slave-updates 和 --log-bin 选项启动 slave。这会导致 slave 将从 master 读取的更 新操作写到自己的二进制日志中。3. 在重设同步状态之前保存所有的证据。如果我们没有任何信息或者只有粗略的信息,这将很难或者不可能追查到这 个问题。需要收集以下证据:o master 上的所有二进制日志o slave 上的所有二进制日志
  56. 56. o 发现问题时,在 master 上执行 SHOW MASTER STATUS 的结果 o 发现问题时,在 master 上执行 SHOW SLAVE STATUS 的结果 o 记录 master 和 slave 的错误日志 4. 用 mysqlbinlog 来检查二进制日志。例如,用以下方法有助于找到有问题的查询: 5. shell> mysqlbinlog -j pos_from_slave_status 6. /path/to/log_from_slave_status | head 一旦收集好了问题的证据,首先将它隔离到一个独立的测试系统上。然后在我们的 bug 数据库 http://bugs.mysql.com/上进可能详细地报告问题。 ‹ MySQL 同步(四)up• MySQL 文档翻译• Add new commentComments Thu, 2007/07/05 - 11:10 — junphine (not verified) 我想问一下,数据库
  57. 57. 我想问一下,数据库同步需要库中的表结构相同,那么我能不能在 Master 上的表中的某个字段不设索引,而在 slave 上建索引? 还有同步会不会将 Slave 中已经存在的数据删除掉(这些数据的 key 和 Master 不同)?• reply Thu, 2007/07/05 - 18:56 — yejr 1. 可以 2. 1. 可以 2. 如果 master 上有删除数据的操作,那么 slave 也会跟着做的 MySQL 方案、培训、支持 给你的祝福,要让你招架不住! • reply Fri, 2007/01/26 - 11:56 — 游客 (not verified) 你好。我想咨询一下 你好。 我想咨询一下,在同步的时候,电脑断电了,重新启动电脑后不能再同步,要重新设置 MASTER_LOG_FILE 和 MASTER_LOG_POS 值才可以继续同步。 请问有什么设置或者方法可以使同步在电脑突然断电重启后还能正常进行?• reply Fri, 2007/01/26 - 14:24 — yejr
  58. 58. 老规矩,先贴上报错 老规矩,先贴上报错信息,mysql 版本,配置等资料。 MySQL 中文网: http://imysql.cn Google MySQL 中文用户群:http://groups.google.com/group/imysql 给你的祝福,要让你招架不住!• reply Sat, 2007/01/27 - 11:11 — 游客 (not verified) 感谢你抽空解答我的 感谢你抽空解答我的问题。下面这些就是版本,错误信息及设置。我刚接触 mysql,请多多指教。 版本:mysql 5.0.20-nt *.err 的错误信息: 070127 10:25:11 InnoDB: Database was not shut down normally! InnoDB: Starting crash recovery. InnoDB: Reading tablespace information from the .ibd files... InnoDB: Restoring possible half-written data pages from the doublewrite InnoDB: buffer... 070127 10:26:22 InnoDB: Starting log scan based on checkpoint at InnoDB: log sequence number 8 3059764932. InnoDB: Doing recovery: scanned up to log sequence number 8 3065007616 InnoDB: Doing recovery: scanned up to log sequence number 8 3070250496 InnoDB: Doing recovery: scanned up to log sequence number 8 3075493376

×