MySQL的复制(5.0.x版)part 2

6.4. 如何设置复制

这里简单描述了如何为你当前的 MySQL服务器设置完整的复制。假设你想要复制主服务器上的所有数据库,并且还没有配置的复制。你需要关闭主服务器来完成下面所列的步骤。
下面的过程针对设置一个从服务器,你可以用来设置多个从服务器。
虽然该方法是设置从服务器的最直接的途径,它并不是唯一的一个。例如,如果你有一个主服务器的数据快照,并且主服务器已经设置了服务器 ID,启用了二进制日志,不需要关闭主服务器或停止对它的更新也可以设置从服务器。详情请参见 6.10节,“复制FAQ”
如果想要管理 MySQL 复制设置,我们建议你通读本章,并尝试 13.6.1节,用于控制主服务器的SQL语句 13.6.2节,用于控制从服务器的SQL语句 中的所有语句。还应熟悉 6.8节,复制启动选项 中描述的复制启动选项。
注释:该程序和后面章节所示的复制 SQL语句需要 SUPER权限。
1.    确保在服务器和从服务器上安装的 MySQL版本与 6.5节,“不同MySQL版本之间的复制兼容性”所示的表兼容。理想情况,应在主服务器和从服务器上使用最近版本的 MySQL
请先证实问题不是出现在最新的 MySQL版本中再通报 bug
2.    在主服务器上为服务器设置一个连接账户。该账户必须授予 REPLICATION SLAVE权限。如果账户仅用于复制 (推荐这样做 ),则不需要再授予任何其它权限。 (关于设置用户 账户和权限的信息,参见 5.8节,“MySQL用户账户管理”)。
假定你的域为 mydomain.com,想要创建用户名为 repl的一个账户,从服务器可以使用该账户从你的域内的任何主机使用密码 slavepass来访问主服务器。要创建该 账户,可使用 GRANT语句:
mysql> GRANT REPLICATION SLAVE ON *.*
    -> TO 'repl'@'%.mydomain.com' IDENTIFIED BY 'slavepass';
 
关于用户账户和权限的更新信息查看 Section 5.8, MySQL User Account Management .
3.    执行 FLUSH TABLES WITH READ LOCK语句来刷新表 ,同时阻止写操作 .
          mysql> FLUSH TABLES WITH READ LOCK
对于 InnoDB表,请注意: FLUSH TABLES WITH READ LOCK还锁定 COMMIT操作。当获得全局读锁定后,可以开始 InnoDB表的文件系统快照。快照不能保证内部 (InnoDB存储引擎内部 )一致性 (因为 InnoDB缓存没有刷新 ),但并不需要关心该问题,因为 InnoDB可以在启动时解决该问题并给出一致的结果。这说明 InnoDB在启动快照时可以进行崩溃恢复,而不会破坏。然而,当保证一致的 InnoDB表快照时,还没有途径来停止 MySQL服务器。
让客户程序保持运行,发出 FLUSH TABLES语句让读锁定保持有效。 (如果退出客户程序,锁被释放)。然后对主服务器上的数据进行快照。
创建快照最简单的途径是使用归档程序对主服务器上的数据目录中的数据库进行二进制备份。例如,在 Unix中使用 tar,或者在 Windows中使用 PowerArchiver WinRARWinZip或者类似的软件。要使用 tar来创建包括所有数据库的归档文件,进入主服务器的数据目录,然后执行命令:
shell> tar -cvf /tmp/mysql-snapshot.tar .
如果你想让归档只包括 this_db数据库,应使用命令:
shell> tar -cvf /tmp/mysql-snapshot.tar ./this_db
然后将归档文件复制到从服务器主机的 /tmp目录。在该机器上,进入从服务器的数据目录,并使用下述命令解压缩归档文件:
shell> tar -xvf /tmp/mysql-snapshot.tar
 
如果从服务器的用户账户与主服务器的不同,你可能不想复制 mysql数据库。在这种情况下,应从归档中排除该数据库。你也不需要在归档中包括任何日志文件或者 master.inforelay-log.info文件。
FLUSH TABLES WITH READ LOCK所置读锁定有效时,读取主服务器上当前的二进制日志名和偏移量值:
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。记录该值。以后设置从服务器时需要使用这些值。它们表示复制坐标,从服务器应从该点开始从主服务器上进行新的更新。
i f the master has been running previously without binary logging enabled, the log name and position values displayed by SHOW MASTER STATUS or mysqldump --master-data will be empty. In that case, the values that you need to use later when specifying the slave's log file and position are the empty string ( '' ) and 4 .
取得快照并记录日志名和偏移量后,可以在主服务器上重新启用写活动:
mysql> UNLOCK TABLES
 
如果你正使用 InnoDB表,理想情况应使用 InnoDB Hot Backup工具,使用该工具可以获得一致的快照而不需要在主服务器上进行锁定,并且可以对应从服务器上使用的快照来记录日志名和偏移量。 Hot Backup是一个附加的非免费 (商业 )工具,没有包含在标准 MySQL分发中。详细信息参见 [url]http://www.innodb.com/manual.php[/url]InnoDB Hot Backup主页。
没有 Hot Backup 工具的话 , InnoDB 的表进行二进制快照的最简单方法就是关闭主服务器 , 然后复制 InnoDB 数据文件、日志文件和表定义 ( 或者称为表格式 fomat) 文件 (.frm 文件 ) 。要记录当前的日志文件名和偏移量,你需要在关闭服务器之前应发出下面的语句:
 
mysql> FLUSH TABLES WITH READ LOCK;
mysql> SHOW MASTER STATUS;
 
 
然后记录我们之前提到的 SHOW MASTER STATUS的输出中显示的日志名和偏移量。记录日志名和偏移量后, 解锁表关闭服务器以确保   服务器关闭时的快照与当前的日志文件和偏移量相对应:
shell> mysqladmin -u root shutdown
有另一个方法同时适用 MyISAMInnoDB:对主服务器上的 SQL进行转储 dump而不是对前面讨论的二进制复制。为了实现,可以在主服务器上使用 mysqldump --master-data,以后将 SQL转储文件装入从服务器。但是,这样比二进制复制要慢一些。
4. 确保主服务器主机上 my.cnf文件的 [mysqld]部分包括一个 log-bin选项。该部分还应有一个 server-id=Master_id选项,其中 master_id必须为 1232�C1之间的一个正整数值。例如:
            [mysqld]
            log-bin=mysql-bin
            server-id=1
如果这些选项不存在 , 添加它们并且重启服务器 . binary logging( 二进制日志 ) 没有启用的情况下 , 服务器是不可能称为复制主服务器的 .
Note : For the greatest possible durability and consistency in a replication setup using InnoDB with transactions, you should use innodb_flush_log_at_trx_commit=1 , sync_binlog=1 , and, before MySQL 5.0.3, innodb_safe_binlog , in the master my.cnf file. ( innodb_safe_binlog is not needed from 5.0.3 on.)
5.停止用于从服务器的服务器并在其 my.cnf文件中添加下面的行:
        [mysqld]
        server-id=slave_id
slave_id值同 Master_id值一样,必须为 1232�C1之间的一个正整数值。并且,从服务器的 ID必须与主服务器的 ID不相同。例如:
[mysqld]
server-id=2
如果设置多个从服务器,每个从服务器必须有一个唯一的 server-id值,必须与主服务器的以及其它从服务器的不相同。可以认为 server-id值类似于 IP地址:这些 ID值能唯一识别复制服务器群集中的每个服务器实例。
如果你没有指定 server-id 的值 , 如果你没有定义 master-host, 它将会被设为 1, 否则就被设为 2. 注意 , server-id 省略时 , 主会拒绝所有从的连接 , 从也会拒绝到主 . 这样,省略 server-id 只适合用二进制日志备份。
 
6 如果对主服务器的数据进行二进制备份,启动从服务器之前将它复制到从服务器的数据目录中。确保对这些文件和目录的权限正确。你用来运行从服务器 的系统帐号必须能够读写这些文件,就如同在主服务器上一样。
如果使用 mysqldum 备份,先启动从服务器。在接下来的步骤里面就将会加载 dump 的文件
 
7 启动从服务器。如果前面已经复制了,用 --skip-slave-start 选项启动从服务器,以便它不立即尝试连接主服务器。你也可能想要用 --logs-warnings 选项启动从服务器 ( 默认设置启用 ) ,以便在错误日志中显示更多的问题相关的信息 ( 例如,网络或连接问题 ) 。放弃的连接将不会记入错误日志,除非这个 option 的值大于 1
 
8 如果使用 mysqldump 备份主服务器的数据,将转储文件装载到从服务器:
shell> mysql -u root -p < dump_file.sql
 
9 在从服务器上执行下面的语句,用你的系统的实际值替换选项值:
mysql> CHANGE MASTER TO
    ->     MASTER_HOST=' master_host_name ',
    ->     MASTER_USER=' replication_user_name ',
    ->     MASTER_PASSWORD=' replication_password ',
    ->     MASTER_LOG_FILE=' recorded_log_file_name ',
->     MASTER_LOG_POS= recorded_log_position ;
 
下面的表显示了字符串选项的最大长度:
Master_Host
60
Master_USER
16
Master_PASSWORD
32
Master_Log_File
255
 
10启动从服务器线程:
   mysql> START SLAVE
执行这些程序后,从服务器应连接主服务器,并补充自从快照以来发生的任何更新。
如果你忘记设置主服务器的 server-id值,从服务器不能连接主服务器。
如果你忘记设置从服务器的 server-id值,在从服务器的错误日志中会出现下面的错误:
Warning: You should set server-id to a non-0 value if master_host is set;
we will force server id to 2, but this MySQL server will not act as a slave.
如果由于其它原因不能复制,从服务器的错误日志中也会出现错误消息。
从服务器复制时,会在其数据目录中发现文件 dmaster.info relay-log.info 。从服务器使用这两个文件跟踪已经处理了多少主服务器的二进制日志。不要移除或编辑这些文件,除非你确切知你正在做什么并完全理解其意义。即使这样,最好是使用 CHANGE MASTER TO 语句来更改复制的参数 . 从服务器将会运用语句中指定的值来自动更新状态文件 .
注释: master.info 内容会覆盖命令行或 in my.cnf 中指定的部分选项。详情参见 6.8节,复制启动选项
一旦有了一个快照,你可以用它根据刚刚描述的从服务器部分来建立其它从服务器。你不需要主服务器的另一个快照;每个从服务器可以使用相同的快照。
 

6.5. 不同MySQL版本之间的复制兼容性

MySQL 5.0中使用的二进制日志格式与以前的版本中所使用的大大不同,特别是在 5.03(字符集处理、 LOAD DATA INFILE)以及 5.04(时区方面 )
我们推荐使用最近的 MySQL 版本,因为复制功能在不断地改进中。我们还推荐主服务器和从服务器使用相同的版本。我们建议升级主服务器和从服务器,运行 alpha beta 版本更新到新的 ( 产品 ) 版本。从 5.0.3 的主向 5.0.2 的从复制会失败 , 5.0.4 的主向 5.0.3 的从复制也会失败 . 一般来讲 , ,运行 MySQL 5.0..x 的从服务器可以与旧的主服务器 ( 即使它们运行的是 MySQL 3.23 4.0 或者 4.1) 一起使用,但不能反过来。
see Section 6.7, “Replication Features and Known Problems”.
注释:你不能从使用新二进制日志格式的主服务器向使用旧二进制日志格式的从服务器复制 (例如,从 MySQL 5.0MySQL 4.1)。。这样操作在复制设置升级服务器时后果严重,参见 6.6节,“升级复制设置”
前面的信息适合协议级复制兼容性。然而,还会有一个约束条件,例如 SQL 级兼容性问题。例如, 5.0 版本的主服务器不能复制到 4.1 版本的从服务器,如果复制语句使用 5.0 版本的 SQL 特性而不是 4.1 版本。这些问题和其它问题均在 6.7节,复制特性和已知问题 中讨论。
 
6.6.  升级复制设置
6.6.1. 将复制升级到5.0
当在复制设置中升级服务器时,升级过程取决于当前的服务器版本和要升级的服务器版本。

6.6.1. 将复制升级到5.0

该节适用于将复制从 MySQL 3.23 4.0 或者 4.1 升级到 5.0 4.0 服务器应为 4.0.3 或更新版。
当将早期 MySQL版本系列主服务器升级到 5.0时,应先确保该主服务器的所有从服务器使用了相同的 5.0.x版本。如果不是这样,你应先升级从服务器。升级从服务器时,应先关闭从服务器,升级到相应 5.0.x版本,然后重启从服务器并重新开始复制。 5.0版本的从服务器能够读取升级前写入的旧的中继日志并执行日志中包含的语句。升级后从服务器创建的中继日志为 5.0格式。
从服务器升级后,关闭主服务器,将它升级到与从服务器相同的 5.0.x版本并重启它。 5.0主服务器能够读取升级前写入的旧的二进制日志并将它们发送到 5.0从服务器。从服务器可以识别旧的格式并正确处理它。升级后主服务器创建的二进制日志采用 5.0格式。这样也可以由 5.0从服务器识别。
换句话说,当升级到 5.0时没有什么措施,只是将主服务器升级到 5.0之前先将从服务器升级到 5.0。请注意从 5.0降级到旧版本不会如此简单:必须确保已经完全处理所有 5.0版本的二进制日志或中继日志,以便在降级前可以移除它们。

6.7. 复制特性和已知问题

一般原则, SQL 级复制兼容性要求主服务器和从服务器均支持使用的特性。如果你在主服务器上运用了一个特定版本的特性 , 但你的从服务器比那个版本低 , 那样就不能完成复制 . 类似的不兼容极有可能在不同系列的版本间发生 , 例如 , 你不能从 5.0 复制到 4.1. 但是 , 这项不兼容也有可能在一个系列的版本复制时发生 . 例如 SLEEP() 函数只在 MySQL5.0.12 及以后的版本中才支持 . 如果你在主服务器里面运用了这个函数 , 那么你就不能复制到一个版本低于 5.0.12 的从服务器上 .
 
如果你计划在 5.1 和以前版本的 MySQL 之间进行复制,你应查阅对应以前版本系列的 MySQL 参考手册,查询该系列复制特征相关信息。
下面列出了关于支持什么和不支持什么的详细信息。关于复制的其它 InnoDB 具体信息参见 15.2.6.5节,“InnoDBMySQL复制
关于存储的程序和触发器的复制问题在 17.4节,“存储子程序和触发程序的二进制日志功能”中讨论。
已知问题: 5.0.17 ,CREATE TRIGGER 的语法更改为包含一个 DEFINER 子句用来指定触发器启动时的访问权限 .( 查看 18.1 "CREATE TRIGGER 语法 ") 尽管如此 , 如果你向从一个低于 5.0.17 的主向一个运行 5.0.17 或者 5.0.19 的从复制时 ,CREATE TRIGGER 这个语句的复制将会失败 , 从服务器的错误为 Definer not fully qualified.
A workaround is to create triggers on the master using a version-specific comment embedded in each CREATE TRIGGER statement:
CREATE /*!50017 DEFINER = 'root'@'localhost' */ TRIGGER ...
这样写的 CREATE TRIGGER 语句将被复制到新版本的从服务器 , 从服务器从注释中提取 DEFINER 子句 , 然后正确执行 .
5.0.20 中这个问题得以修复 .
・         AUTO_INCREMENT , LAST_INSERT_ID() , TIMESTAMP 的值可以被正确复制 . 下面是特殊情况 ( to the following exceptions.
INSERT DELAYED ... VALUES(LAST_INSERT_ID()) 在主与从上插入不同值 (Bug#20819) . 这个在 5.1 中修复运用基于行或者混合格式的二进制日志 .
5.0.26 , 运用了 LAST_INSERT_ID() 的存储过程不能被正确复制 .
当一个语句用了向一个 AUTO_INCREMENT 列插入的存储功能时 , 产生的 AUTO_INCREMENT 值不会被写入二进制日志 , 所以一些时候从服务器上就会写入不同值 .
ALTER TABLE 向一个表增加一个 AUTO_INCREMENT 可能不后会在主和从上产生一样的顺序 . 这样问题发生的原因是 : 行编号的顺序取决于这个表用的特定存储引擎和这些列插入的顺序 . 如果主和从的顺序必须一样 , 那么这些行必须在分配 AUTO_INCREMENT 值之前就已经存储了 . 假定你想要向表 t1 增加一个 AUTO_INCREMENT , 以下的几个语句会产生一个新表 t2 t1 一样 , 但是有一个 identical .
                CREATE TABLE t2 LIKE t1;
                ALTER TABLE t2 ADD id INT AUTO_INCREMENT PRIMARY KEY;
                INSERT INTO t2 SELECT * FROM t1 ORDER BY col1, col2;
这是架设 t1 表有 col1 col2
重要 : 为了保证主从一样的顺序 ,t1 里面的所有列必须用 ORDER BY 排序
以上给出的语句主要受 CREATE TABLE ... LIKE 的限制 . 外键的定义还有 DATA DIRECTORY , INDEX DIRECTORY 的表选项 将被忽略 . 如果一个表包含了上述特性 , 那么就用 CREATE TABLE 语句来创建 t2, 就和创建 t1 的语句一样 , 但是加上一个 AUTO_INCREMENT 的列
不管用来创建和增加 AUTO_INCREMENT 给副本用的是什么方法 , 最后一步都是删除原始表 , 然后将副本重命名 .
                DROP t1;
                ALTER TABLE t2 RENAME t1;
查看 Section B.1.7.1, “Problems with ALTER TABLE”.
・         特定的函数在以下的一些情况下不能被恰当复制 :
   ・         USER() , CURRENT_USER() , UUID() , VERSION() , and LOAD_FILE() 函数没有更改的被复制 , 这样在从服务器上不会可靠的执行 .
   ・         5.0.13 , SYSDATE() 不再和 NOW() 等同 . 意思是 SYSDATE() 不是安全复制的 , 因为二进制日志中的 SET TIMESTAMP 语句完全不影响它 , 而且不起决定作用 . 为了避免这样 , 你可以启动服务器的时候带 --sysdate-is-now 这个选项来将 SYSDATE() 作为 NOW() 的别名
   ・         GET_LOCK() , RELEASE_LOCK() , IS_FREE_LOCK() , and IS_USED_LOCK() 这些控制用户级的锁的函数被复制时从并不知道主的并发连接情况 . 因此这些函数不应该被用来插到主的表里面 , 因为从服务器上的内容将会不同 .( 例如 , 不要发出这样的语句 INSERT INTO mytable VALUES(GET_LOCK(...)) .)
为了避开之前的限制 , 你可以用这样的策略 : 将有问题的函数的结果保存在一个用户变量中 , 然后在后面的语句中引用它 . 例如 , 下面的 INSERT 语句由于 UUID() 函数导致有问题
                INSERT INTO t VALUES(UUID());
为了避免问题 , 用下面的语句替代 :
                SET @my_uuid = UUID();
                INSERT INTO t VALUES(@my_uuid);
这些语句被复制因为 @my_uuid 的值作为一个用户变量保存于二进制日志中 , 它优先于 INSERT 语句保存 , 然后能够被 INSERT 所使用 .
同样的思想也适用于多行插入 , 但是用起来更麻烦些 . 对于一个两行的插入 , 你可以这样做 :
                SET @my_uuid1 = UUID(); @my_uuid2 = UUID();
                INSERT INTO t VALUES(@my_uuid1),(@my_uuid2);
尽管如此 , 如果行数很多或者未知 , 这个方法就十分困难甚至不可行 . 例如 , 你不能将下面的语句转换 , 在它里面每个独立的用户变量与每一个行关联 .
                INSERT INTO t2 SELECT UUID(), * FROM t1;
 
・         用户的权限仅当 mysql 数据库被复制才会被复制 . 这就是说 GRANT , REVOKE , SET PASSWORD , CREATE USER , and DROP USER 语句要在从服务器上起作用仅仅当复制建立时包括了 mysql 数据库 .
如果你复制所有的数据库 , 但是不希望那些影响用户权限的语句被复制 , 那么建立从服务器不要复制 mysql 数据库 , --replicate-wild-ignore-table=mysql.% 选项 . 从服务器就会识别出与权限相关的 SQL 语句不会起作用 , 这样就不会执行这些语句了 .
 
・        FOREIGN_KEY_CHECKS , SQL_MODE , UNIQUE_CHECKS , and SQL_AUTO_IS_NULL 这些变量在 MySQL5.0 里面都会被复制 . 系统变量 storage_engine (also known as table_type ) 不会被复制 , 这对于不同存储引擎间的复制是件好事 .
・       5.0.3 开始 ( 主和从 ), 即使主和从有不同的全局字符设置变量 global character set variables , 复制也能进行 . 5.0.4 开始 ( 主和从 ), 即使主和从有不同的全局时区变量 global time zone variables, 也能进行 .
  • The following applies to replication between MySQL servers that use different character sets:
    1. If the master uses MySQL 4.1, you must always use the same global character set and collation on the master and the slave, regardless of the MySQL version running on the slave. (These are controlled by the --character-set-server and --collation-server options.) Otherwise, you may get duplicate-key errors on the slave, because a key that is unique in the master character set might not be unique in the slave character set. Note that this is not a cause for concern when master and slave are both MySQL 5.0 or later.
    2. If the master is older than MySQL 4.1.3, the character set of any client should never be made different from its global value because this character set change is not known to the slave. In other words, clients should not use SET NAMES, SET CHARACTER SET, and so forth. If both the master and the slave are 4.1.3 or newer, clients can freely set session values for character set variables because these settings are written to the binary log and so are known to the slave. That is, clients can use SET NAMES or SET CHARACTER SET or can set variables such as collation_client or collation_server. However, clients are prevented from changing the global value of these variables; as stated previously, the master and slave must always have identical global character set values.
    3. If you have databases on the master with character sets that differ from the global character_set_server value, you should design your CREATE TABLE statements so that tables in those databases do not implicitly rely on the database default character set (see Bug#2326). A good workaround is to state the character set and collation explicitly in CREATE TABLE statements.
  • If the master uses MySQL 4.1, the same system time zone should be set for both master and slave. Otherwise some statements will not be replicated properly, such as statements that use the NOW() or FROM_UNIXTIME() functions. You can set the time zone in which MySQL server runs by using the --timezone=timezone_name option of the mysqld_safe script or by setting the TZ environment variable. Both master and slave should also have the same default connection time zone setting; that is, the --default-time-zone parameter should have the same value for both master and slave. Note that this is not necessary when the master is MySQL 5.0 or later.
・       CONVERT_TZ(...,...,@@global.time_zone) 不能被正常复制 , 仅仅当主和从是 5.0.4 及之后的版本 CONVERT_TZ(...,...,@@session.time_zone) 才能被正确复制 .
・       会话变量 (session) 当用在更新表的语句中时不能被正常复制 . 例如 , SET MAX_JOIN_SIZE=1000 , 后面接上 INSERT INTO mytable VALUES(@@MAX_JOIN_SIZE) 将不会在主和从上插入相同数据 . 这不适用于以下情况 : SET TIME_ZONE=... 后面接 INSERT INTO mytable VALUES(CONVERT_TZ(...,...,@@time_zone)) ,, 这句话在 5.0.4 上能正确复制 .
・       将主上的事务性 (transactional) 表而从上面是非事务性的表 (non-taransactional) 这样的复制可能是可以的 . 例如 , 你可以复制一个 InnoDB 主的表作为一个 MyISAM 的从的表 . 尽管如此 , 如果你这么做了 , 当从服务器在 BEGIN/COMMIT 之间停止时会出现问题 , 因为从服务器会在 BEGIN 块的起始处重启 .
・       5.0 里面涉及有用户定义变量 ( 形如 @ var_name ) 的更新语句可以被正确复制 . 但是 4.1 之前的版本不支持 . 注意 5.0 开始用户变量名称是不敏感的 case insensitive . 在配置 5.0 和老版本间的复制时应该考虑这个情况 .
・       带有 RAND() 或者用户定义变量的非延迟 (non-delay) INSERT 语句可以被正确复制 . 尽管如此 , 如果用 INSERT DELAYED 这样的语句可能会导致主从的结果不一致 .
・       从可以通过 SSL 连接到主
・      视图总是被复制到从 . 视图由它自己的名字过滤 , 而不是由它们相关的表 . 这表示即使一个视图里面含有一个被 replication-ignore-table 规则所过滤掉的表 , 这个视图也会被复制 . 因此应该注意保证视图没有复制表里面的数据 , 一般会因为安全原因而过滤掉 .
・       5.0 里面 ( 5.0.3 开始 ), 有一个全局系统变量 slave_transaction_retries. 如果复制过程中从上的 SQL 线程执行一个事务时失败 ( 由于 an InnoDB deadlock, 或者它超过了下列值 InnoDB innodb_lock_wait_timeout, 或者 NDBCluster TransactionDeadlockDetectionTimeout 或者 TransactionInactiveTimeout ), 事务会自动重试 slave_transaction_retries 定义的次数然后停止产生一个错误 . 默认的值是 10. 5.0.4 开始 , 这个重试的总数可以在 SHOW STATUS 的输出中看见 . 查看 Section 5.2.5, “Status Variables”.
・       如果主上的 CREATE TABLE 语句中使用了 DATA DIRECTORY or INDEX DIRECTORY 的表选项 , 这个选项也用在从上 . 但是如果从的上面没有相应的目录或者存在但是不能访问的话会产生问题 .MySQL 支持一个 sql_mode 的选项称为 NO_DIR_IN_CREATE. 如果从服务器运行没有启用这个 SQL 模式的话 , 它在复制 CREATE TABLE 时就会忽略 DATA DIRECTORY INDEX DIRECTORY. 这样的结果是 MyISAM 数据和索引文件都会在这个表的数据库文件夹下面创建 .
  • It is possible for the data on the master and slave to become different if a statement is designed in such a way that the data modification is non-deterministic; that is, left to the will of the query optimizer. (This is in general not a good practice, even outside of replication.) For a detailed explanation of this issue, see Section B.1.8.1, “Open Issues in MySQL”.
・       主运行 4.1, 从运行 5.0 , LOAD TABLE FROM MASTER 可能会损坏表数据 , 并且不被支持 . (Bug#16261)
・       以下仅仅适用于或者主或者从正运行 5.0.3 及之前版本的 . 如果主上的一个 LOAD DATA INFILE 被阻断 ( 完整性约束破坏 , 中断连接 , 等等 ), 从直接跳过整个 LOAD DATA INFILE 文件 . 这意味着这个命令在被中断之前永久性的插入或更新了纪录的话 , 这些更改将不会复制到从 .
・       一些 FLUSH 语句将不会被记录到日志因为他们复制到从的时候可能引起问题 : FLUSH LOGS , FLUSH MASTER , FLUSH SLAVE , and FLUSH TABLES WITH READ LOCK. 举语法例子 , 查看 Section 13.5.5.2, “FLUSH Syntax”. FLUSH TABLES , ANALYZE TABLE , OPTIMIZE TABLE , and REPAIR TABLE 这些语句被写入二进制日志 , 然后复制给从 . 这一般不存在问题因为这些语句并不修改表数据 . 但是 , 在一定情况下会引起麻烦 . 如果你复制了 mysql 数据库里面的权限表 , 没有用 GRANT 直接更新了它们 , 你必须在从上面发出 FLUSH PRIVILEGES 让新权限生效 . 当你重命名一个 MyISAM ( 并且这个表是一个 MERGE 表的部分 ) , 如果你用 FLUSH TABLES, 你必须在从上手动的发出 FLUSH TABLES. 这些语句不会被写入二进制日志 , 除非你指定了 NO_WRITE_TO_BINLOG 或者它的别名 LOCAL
・       当一个服务器关闭或者重启时 , 他的内存 MEMORY ( HEAP ) 表变为空的 . 主将这个影响复制给从像以下这样 : 主启动后运用每个 MEMORY 表的第一次 , 它日志记录一个时间提醒从表需要被清空 ( 通过在二进制日志中为这个表写入一个 DELETE 语句 ).. See Section 14.4, “The MEMORY (HEAP) Storage Engine”, for more information about MEMORY tables.
・       临时表被复制 , 除了以下这种情况 : 你关闭了服务器 ( 不仅是从线程 ), 并且你已经复制了用于更新但是还没有在从上执行的临时表 . 如果你关闭了从服务器 , 当从重启的时候 , 那些更新所需要的临时表救不再可用了 . 为了避免这个问题 , 不要在从有临时表打开的时候关闭它 . 代替方法 , 用下面的过程 :
    1. Issue a STOP SLAVE statement. 发出一个STOP SLAVE语句
    2. Use SHOW STATUS to check the value of the Slave_open_temp_tables variable. SHOW STATUS查看Slave_open_temp_tables变量的值
    3. If the value is 0, issue a mysqladmin shutdown command to stop the slave. 如果这个值是0,发出mysqladmin shutdown命令来停止从
    4. If the value is not 0, restart the slave threads with START SLAVE. 如果这个值不是0,START SLAVE重启从线程
    5. Repeat the procedure later until the Slave_open_temp_tables variable is 0 and you can stop the slave. 隔一会重复这个过程直到Slave_open_temp_tables的值为0然后你救可以停止从了.
・       用表的别名来进行多个表 DELETE 删除的语法在 4.0 4.1 里面发生了改变 . 4.0 里面 , 你要用要删除的行相关的表的真实的表名
                DELETE test FROM test AS t1, test2 WHERE ...
4.1 里面 , 你必须用别名 :
                DELETE t1 FROM test AS t1, test2 WHERE ...
如果你用了这样的 DELETE 语句 , 语法的改变意味着 4.0 的主不能复制到 4.1( 或者更高 ) 的从
・       如果你用了 --log-slave-updates 选项那么以一种环形的主 / 从关系进行连接是安全的 . 你可以创建如下的设置 :
                A -> B -> C -> A
但是 , 许多语句不能这样工作在这样的设置下 . 除非你的客户端代码编写已经考虑到了不同服务器不同顺序下更新可能产生的问题 .
server ID 是用二进制日志事件编码的 , 因此服务器 A 知道它读的某个事件最初是由它自己产生的而不会执行这个事件 ( 除非 A 启动时有 --replicate-same-server-id 选项 , 这个只在很少的情况下有意义 ). 这样就不会有无穷的循环 . 这种环形的设置仅仅当你的表之间没有冲突的更新时才会工作 . 还句话说 , 如果你在 A C 里面都插入了数据 , 你决不能在 A 里面插入行 , 而这个行又跟插入 C 里面的一个行有个关键字冲突 . 你也不应该更新相同的行在两个服务器上 , 如果这些更新应用的次序十分重要 .
・       如果从的一个语句产生错误 , 从的 SQL 线程中止 , 然后从写入一个消息到它的错误日志中 . 你这个时候应该手动连接到从 , 然后找出问题的原因 ( 这个时候 SHOW SLAVE STATUS 十分有用 ) , 然后修复这个问题 ( 例如 , 你可能需要创建一个不存在的表 ), 然后运行 START SLAVE .
・       关闭主然稍后再重启是十分安全的 . 当从失去了跟主的连接后 , 从会直接就发起重新连接 , 如果失败会周期性重连 . 默认是每 60s 重连一次 . 可以用 --master-connect-retry 来更改 . 从也能处理网络连接损耗 . 尽管如此仅在 slave_net_timeout 秒数的时间内从没有从主那里收到数据 , 从才会提示网络损耗 . 如果你的网络损耗很短 , 你可能想要减小 slave_net_timeout 的值 . See Section 5.2.3, “System Variables”.
・         关闭从服务器(净关闭)也很安全,因为它可以跟踪它离开的地点。不纯净的关闭操作会产生问题,特别是系统关闭前硬盘缓存未刷新到硬盘上时。如果有不间断电源,可以大大提高系统容错能力。不纯净的关闭主服务器会造成主服务器上的表和二进制日志内容之间的不一致性;在主服务器上使用 InnoDB 表和 --innodb-safe-binlog 选项可以避免该问题。参见 5.11.3节,二进制日志
( 注释: MySQL 5.1 中不需要 --innodb-safe-binlog ,由于引入了 XA 事务支持已经作废了)。
・         主端 crash 可能导致主的二进制日志最后的位置比从读的最近的位置要少 , 因为主的二进制文件没有被 flush 刷新 . 这可能导致主起来后从不能读 . 在主的 my.cnf 中设置 sync_binlog=1 帮助最小化这个问题因为它使得主刷新它的二进制日志更加频繁 .
・         由于 MyISAM表的非事务属性,可以有一个语句只是更新一个表并返回错误代码。例如,多行插入时有一个行超过键值约束,或者如果长的更新语句更新部分行后被杀掉了。如果发生在主服务器上,除非错误代码合法并且语句执行产生相同的错误代码,从服务器线程将退出并等待数据库管理员决定如何做。如果该错误代码验证行为不理想,可以用 --slave-skip-errors选项掩盖 (忽视 )部分或全部错误。
・         如果从 BEGIN/COMMIT 系列的非事务表更新事务表,如果提交事务前更新非事务表,对二进制日志的更新可能会不同步。这是因为事务提交后才被写入二进制日志。
・         事务混合更新事务表和非事务表时,二进制日志中语句的顺序是正确的,即使在 ROLLBACK时,所有需要的语句也会写入二进制日志。但是如果在第 1个连接的事务完成前,第 2个连接更新非事务表,语句记入日志时会出现顺序错误,因为第 2个连接的更新执行完后立即写入日志,而不管第 1个连接执行的事务的状态如何。
注意 : 在复制环境里 , 你不应该用事务同时更新事务性和非事务性的表格 .
 
・         浮点数的转换比较可能产生主从的数据不一致 , 这是由于计算机结构 , 编译器等 . . See Section 12.2.2, “Type Conversion in Expression Evaluation”, and Section B.1.5.8, “Problems with Floating-Point Comparisons”.

你可能感兴趣的:(数据库,mysql,复制,休闲,mysql5.0)