潜龙勿用,见龙在田
全部博文(540)
分类: Mysql/postgreSQL
2009-01-08 16:38:35
注释:你不能从使用新二进制日志格式的主服务器向使用旧二进制日志格式的从服务器复制(例如,从MySQL 5.0到MySQL 4.1)。。这样操作在复制设置升级服务器时后果严重,参见。
我们推荐使用最近的MySQL版本,因为复制功能在不断地改进中。我们还推荐主服务器和从服务器使用相同的版本。我们建议升级主服务器和从服务器,运行alpha或beta版本到新的(产品)版本。在许多情况下,从新的主服务器向旧的从服务器复制将会失败。一般原则,运行MySQL 5.1.x的从服务器可以与旧的主服务器(可以运行MySQL 3.23、4.0或者4.1)一起使用,但不能反过来。
下表描述了可以用于MySQL 5.1从属复制服务器的选项。你可以在命令行中或在选项文件中指定这些选项。
某些从服务器复制选项按特殊方式处理,当从服务器启动时如果master.info文件存在并且包含选项值,它们将被忽略掉。下面的选项按这种方式处理:
· --master-host
· --master-user
· --master-password
· --master-port
· --master-connect-retry
· --master-ssl
· --master-ssl-ca
· --master-ssl-capath
· --master-ssl-cert
· --master-ssl-cipher
· --master-ssl-key
下面的例子显示了如何更广泛地使用启动选项来配置从服务器:
[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
下面列出了控制复制的启动选项:许多选项可以在服务器运行时通过CHANGE MASTER TO语句重新进行设置。
· --logs-slave-updates
通常情况,从服务器从主服务器接收到的更新不记入它的二进制日志。该选项告诉从服务器将其SQL线程执行的更新记入到从服务器自己的二进制日志。为了使该选项生效,还必须用--logs-bin选项启动从服务器以启用二进制日志。如果想要应用链式复制服务器,应使用--logs-slave-updates。例如,可能你想要这样设置:
A -> B -> C也就是说,A为从服务器B的主服务器,B为从服务器C的主服务器。为了能工作,B必须既为主服务器又为从服务器。你必须用--logs-bin启动A和B以启用二进制日志,并且用--logs-slave-updates选项启动B。
· --logs-warnings
让从服务器向错误日志输出更详细的关于其执行操作的消息。例如,通知你网络/连接失败后已经成功重新连接,并通知你每个从服务器线程如何启动。该选项默认启用;要想禁用它,使用--skip-logs-warnings。放弃的连接不记入错误日志,除非该值大于1。
请注意该选项的效果不限于复制。可以对服务器的部分动作产生警告。
· --master-connect-retry=seconds
在主服务器宕机或连接丢失的情况下,从服务器线程重新尝试连接主服务器之前睡眠的秒数。如果主服务器.info文件中的值可以读取则优先使用。如果未设置, 默认值为60。
· --read-only
该选项让从服务器只允许来自从服务器线程或具有SUPER权限的用户的更新。可以确保从服务器不接受来自客户的更新。
· --relay-log-purge={0|1}
禁用或启用不再需要中继日志时是否自动清空它们。默认值为1(启用)。这是一个全局变量,可以用SET GLOBAL Relay_log_purge动态更改。
· --replicate-do-db=db_name
告诉从服务器限制默认数据库(由USE所选择)为db_name的语句的复制。要指定多个数据库,应多次使用该选项,每个数据库使用一次。请注意不复制跨数据库的语句,例如当已经选择了其它数据库或没有数据库时执行UPDATE some_db.some_table SET foo='bar'。如果需要跨数据库进行更新,使用--replicate-wild-do-table=db_name.%。请读取该选项列表后面的注意事项。
一个不能按照期望工作的例子:如果用--replicate-do-db=sales启动从服务器,并且在主服务器上执行下面的语句,UPDATE语句不会复制:
USE prices;
UPDATE sales.january SET amount=amount+1000;
如果需要跨数据库进行更新,应使用--replicate-wild-do-table=db_name.%。
“只检查默认数据库”行为的主要原因是语句自己很难知道它是否应被复制(例如,如果你正使用跨数据库的多表DELETE语句或多表UPDATE语句)。如果不需要,只检查默认数据库比检查所有数据库要快得多。
· --replicate-do-table=db_name.tbl_name
告诉从服务器线程限制对指定表的复制。要指定多个表,应多次使用该选项,每个表使用一次。同--replicate-do-db对比,允许跨数据库更新。请读取该选项列表后面的注意事项。
· --replicate-ignore-db=db_name
告诉从服务器不要复制默认数据库(由USE所选择)为db_name的语句。要想忽略多个数据库,应多次使用该选项,每个数据库使用一次。如果正进行跨数据库更新并且不想复制这些更新,不应使用该选项。请读取该选项后面的注意事项。
一个不能按照期望工作的例如:如果用--replicate-ignore-db=sales启动从服务器,并且在主服务器上执行下面的语句,UPDATE语句不会复制:
USE prices;
UPDATE sales.january SET amount=amount+1000;
如果需要跨数据库更新,应使用--replicate-wild-ignore-table=db_name.%。
· --replicate-ignore-table=db_name.tbl_name
告诉从服务器线程不要复制更新指定表的任何语句(即使该语句可能更新其它的表)。要想忽略多个表,应多次使用该选项,每个表使用一次。同--replicate-ignore-db对比,该选项可以跨数据库进行更新。请读取该选项后面的注意事项。
· --replicate-wild-do-table=db_name.tbl_name
告诉从服务器线程限制复制更新的表匹配指定的数据库和表名模式的语句。模式可以包含‘%’和‘_’通配符,与LIKE模式匹配操作符具有相同的含义。要指定多个表,应多次使用该选项,每个表使用一次。该选项可以跨数据库进行更新。请读取该选项后面的注意事项。
例如:--replicate-wild-do-table=foo%.bar%只复制数据库名以foo开始和表名以bar开始的表的更新。
如果表名模式为%,可匹配任何表名,选项也适合数据库级语句(CREATE DATABASE、DROP DATABASE和ALTER DATABASE)。例如,如果使用--replicate-wild-do-table=foo%.%,如果数据库名匹配模式foo%,则复制数据库级语句。
要想在数据库或表名模式中包括通配符,用反斜线对它们进行转义。例如,要复制名为my_own%db的数据库的所有表,但不复制my1ownAABCdb数据库的表,应这样转义‘_’和‘%’字符:--replicate-wild-do-table=my\_own\%db。如果在命令行中使用选项,可能需要双反斜线或将选项值引起来,取决于命令解释符。例如,用bash外壳则需要输入--replicate-wild-do-table=my\\_own\\%db。
· --replicate-wild-ignore-table=db_name.tbl_name
告诉从服务器线程不要复制表匹配给出的通配符模式的语句。要想忽略多个表,应多次使用该选项,每个表使用一次。该选项可以跨数据库进行更新。请读取该选项后面的注意事项。
例如:--replicate-wild-ignore-table=foo%.bar%不复制数据库名以foo开始和表名以bar开始的表的更新。
关于匹配如何工作的信息,参见--replicate-wild-do-table选项的描述。在选项值中包括通配符的规则与--replicate-wild-ignore-table相同。
· --replicate-rewrite-db=from_name->to_name
告诉从服务器如果默认数据库(由USE所选择)为主服务器上的from_name,则翻译为to_name。只影响含有表的语句(不是类似CREATE DATABASE、DROP DATABASE和ALTER DATABASE的语句),并且只有from_name为主服务器上的默认数据库时。该选项不可以跨数据库进行更新。请注意在测试--replicate-*规则之前翻译数据库名。
如果在命令行中使用该选项, ‘>’字符专用于命令解释符,应将选项值引起来。例如:
shell> mysqld --replicate-rewrite-db="olddb->newdb"· --skip-slave-start
告诉从服务器当服务器启动时不启动从服务器线程。使用START SLAVE语句在以后启动线程。
· --slave_compressed_protocol={0|1}
如果该选项设置为 1,如果从服务器和主服务器均支持,使用压缩从服务器/主服务器协议。
· --slave-net-timeout=seconds
放弃读之前从主服务器等候更多数据的秒数,考虑到连接中断和尝试重新连接。超时后立即开始第1次重试。由--master-connect-retry选项控制重试之间的间隔。
· --slave-skip-errors=[err_code1,err_code2,... | all]
通常情况,当出现错误时复制停止,这样给你一个机会手动解决数据中的不一致性问题。该选项告诉从服务器SQL线程当语句返回任何选项值中所列的错误时继续复制。
如果你不能完全理解为什么发生错误,则不要使用该选项。如果复制设置和客户程序中没有bug,并且MySQL自身也没有bug,应不会发生停止复制的错误。滥用该选项会使从服务器与主服务器不能保存同步,并且你找不到原因。
对于错误代码,你应使用从服务器错误日志中错误消息提供的编号和SHOW SLAVE STATUS的输出。从服务器按下面评估--replicate-*规则,确定是否执行或忽视语句:
1. 是否有--replicate-do-db或--replicate-ignore-db规则?
· 有:测试--binlog-do-db和--binlog-ignore-db(参见)。测试结果是什么?
o 忽视语句:忽视并退出。
o 许可语句:不立即执行语句。推迟决策;继续下一步。
· 没有:继续下一步。
2. 我们目前正执行保存的程序或函数吗?
· 是:执行查询并退出。
· 否:继续下一步。
3. 是否有--replicate-*-table规则?
· 没有:执行查询并退出。
· 有:继续下一步并开始按所示顺序评估表规则(首先是非通配规则,然后是通配规则)。只有待更新的表根据这些规则进行比较(INSERT INTO sales SELECT * FROM prices:只有sales根据这些规则进行比较)。如果要更新几个表(多表语句),第1个匹配的表(匹配“do”或“ignore”)获赢。也就是说,根据这些规则比较第1个表。然后,如果不能进行决策,根据这些规则比较第2个表等等。
4. 是否有--replicate-do-table规则?
· 有:表匹配吗?
o 是:执行查询并退出。
o 否:继续下一步。
· 没有:继续下一步。
5. 是否有--replicate-ignore-table规则?
· 有:表匹配吗?
o 是:忽视查询并退出。
o 否:继续下一步。
· 没有:继续下一步。
6. 是否有--replicate-wild-do-table规则?
· 有:表匹配吗?
o 是:执行查询并退出。
o 否:继续下一步。
· 没有:继续下一步。
7. 是否有--replicate-wild-ignore-table规则?
· 有:表匹配吗?
o 是:忽视查询并退出。
o 否:继续下一步。
· 没有:继续下一步。
8. 没有匹配的--replicate-*-table规则。要根据这些规则测试其它表吗?
· 是:执行循环。
· 否:我们现在已经测试了所有待更新的表,结果不能匹配任何规则。是否有--replicate-do-table或--replicate-wild-do-table规则?
o 有:有“do”规则但不匹配。忽视查询并退出。
o 没有:执行查询并退出。
Q:如果主服务器正在运行并且不想停止主服务器,怎样配置一个从服务器?
A:有多种方法。如果你在某时间点做过主服务器备份并且记录了相应快照的二进制日志名和偏移量(通过SHOW MASTER STATUS命令的输出),采用下面的步骤:
1. 确保从服务器分配了一个唯一的服务器ID号。
2. 在从服务器上执行下面的语句,为每个选项填入适当的值:
mysql> CHANGE MASTER TO
-> MASTER_HOST='master_host_name',
-> MASTER_USER='master_user_name',
-> MASTER_PASSWORD='master_pass',
-> MASTER_LOG_FILE='recorded_log_file_name',
-> MASTER_LOG_POS=recorded_log_position;
3. 在从服务器上执行START SLAVE语句。
如果你没有备份主服务器,这里是一个创建备份的快速程序。所有步骤都应该在主服务器主机上执行。
1. 发出该语句:
mysql> FLUSH TABLES WITH READ LOCK;
2. 仍然加锁时,执行该命令(或它的变体):
shell> tar zcf /tmp/backup.tar.gz /var/lib/mysql
3. 发出该语句并且确保记录了以后用到的输出:
mysql>SHOW MASTER STATUS;
4. 释放锁:
mysql> UNLOCK TABLES;
一个可选择的方法是,转储主服务器的SQL来代替前面步骤中的二进制复制。要这样做,你可以在主服务器上使用mysqldump --master-data,以后装载SQL转储到到你的从服务器。然而,这比进行二进制复制速度慢。
不管你使用这两种方法中的那一个,当你有一个快照和记录了日志名与偏移量时,后来根据说明操作。你可以使用相同的快照建立多个从服务器。一旦你拥有主服务器的一个快照,可以等待创建一个从服务器,只要主服务器的二进制日志完整。两个能够等待的时间实际的限制是指在主服务器上保存二进制日志的可用硬盘空间和从服务器同步所用的时间。
你也可以使用LOAD DATA FROM MASTER。这是一个方便的语句,它传输一个快照到从服务器并且立即调整日志名和偏移量。将来,LOAD DATA FROM MASTER将成为创建从服务器的推荐方法。然而需要注意,它只工作在MyISAM 表上并且可能长时间持有读锁定。它并不象我们希望的那样高效率地执行。如果你有大表,执行FLUSH TABLES WITH READ LOCK语句后,这时首选方法仍然是在主服务器上制作二进制快照。
Q:从服务器需要始终连接到主服务器吗?
A:不,不需要。从服务器可以宕机或断开连接几个小时甚至几天,重新连接后获得更新信息。例如,你可以在通过拨号的链接上设置主服务器/从服务器关系,其中只是偶尔短时间内进行连接。这意味着,在任何给定时间,从服务器不能保证与主服务器同步除非你执行某些特殊的方法。将来,我们将使用选项来阻塞主服务器直到有一个从服务器同步。
Q:我怎样知道从服务器与主服务器的最新比较? 换句话说,我怎样知道从服务器复制的最后一个查询的日期?
A:你可以查看SHOW SLAVE STATUS语句的Seconds_Behind_Master列的结果。参见。
当从服务器SQL线程执行从主服务器读取的事件时,它根据事件时间戳修改自己的时间(这是TIMESTAMP能够很好复制的原因)。在SHOW PROCESSLIST语句输出的Time列内,为从服务器SQL线程显示的秒数是最后一个复制事件的时间戳和从服务器主机的实际时间之间相差的秒数。你可以使用它来确定最后一个复制事件的日期。注意,如果你的从服务器与主服务器连接断开一个小时,然后重新连接,在SHOW PROCESSLIST结果中,你可以立即看到从服务器SQL线程的Time值为3600。这可能是因为从服务器执行的语句是一个一小时之前的。
Q:我怎样强制主服务器阻塞更新直到从服务器同步?
A:使用下面的步骤:
1. 在主服务器上,执行这些语句:
mysql> FLUSH TABLES WITH READ LOCK;
mysql> SHOW MASTER STATUS;
记录SHOW语句的输出的日志名和偏移量。这些是复制坐标。
2. 在从服务器上,发出下面的语句,其中Master_POS_WAIT()函数的参量是前面步骤中的得到的复制坐标值:
mysql> SELECT MASTER_POS_WAIT('log_name', log_offset);
SELECT语句阻塞直到从服务器达到指定的日志文件和偏移量。此时,从服务器与主服务器同步,语句返回。
3. 在主服务器上,发出下面的语句允许主服务器重新开始处理更新:
mysql> UNLOCK TABLES;
Q:怎样通过复制来提高系统的性能?
A:你应将一个服务器设置为主服务器并且将所有写指向该服务器。然后根据预算配置尽可能多的从服务器以及栈空间,并且在主服务器和从服务器之间分发读取操作。你也可以用--skip-innodb、--skip-bdb、--low-priority-updates以及--delay-key-write=ALL选项启动从服务器,以便在从服务器端提高速度。在这种情况下,为了提高速度,从服务器使用非事务MyISAM表来代替InnoDB和BDB表。
Q:MySQL复制能够何时和多大程度提高系统性能?
A:MySQL复制对于频繁读和频繁写的系统具有最大好处。理论上,通过使用单个主服务器/多从服务器设置,可以通过添加更多的从服务器来扩充系统,直到用完网络带宽,或者你的更新负载已经增长到主服务器不能处理的点。
在获得的收益开始吃平之前,为了确定可以有多少从服务器,以及可以将你的站点的性能提高多少,需要知道查询模式,并且要通过基准测试并根据经验确定一个典型的主服务器和从服务器中的读取(每秒钟读取量,或者max_reads)吞吐量和写(max_writes)吞吐量的关系。通过一个假设的带有复制的系统,本例给出了一个非常简单的计算结果。
假设系统负载包括10%的写和90%的读取,并且我们通过基准测试确定max_reads是1200 –2 × max_writes。换句话说,如果没有写操作,系统每秒可以进行1,200次读取操作,平均写操作是平均读操作所用时间的两倍,并且关系是线性的。我们假定主服务器和每个从服务器具有相同的性能,并且我们有一个主服务器和N个从服务器。那么,对于每个服务器(主服务器或从服务器),我们有:
reads = 1200 – 2 × writes
reads = 9 × writes / (N + 1) (读取是分离的, 但是写入所有服务器)
9 × writes / (N + 1) + 2 × writes = 1200
writes = 1200 / (2 + 9/(N+1))
最后的等式表明了N个从服务器的最大写操作数,假设最大可能的读取速率是每分钟1,200次,读操作与写操作的比率是9。
如上分析可以得到下面的结论:
· 如果N = 0(这表明没有复制),系统每秒可以处理大约1200/11 = 109个写操作。
· 如果N = 1,每秒得到184个写操作。
· 如果N = 8,每秒得到400个写操作。
· 如果N = 17,每秒得到480个写操作。
· 最后,当 N 趋于无穷大(以及我们预算的负无穷大)时,可以得到非常接近每秒600个写操作,系统吞吐量增加将近5.5倍。然而,如果只用8个服务器,增加接近4倍。
请注意,这些计算假设网络带宽无穷大并忽略掉了其它一些因素,那些因素可能对系统产生重要的影响。在许多情况下,不能执行与刚才类似的计算,即如果添加N台复制从服务器,应该准确预报系统将发生哪些影响。回答下面的问题应能够帮助你确定复制是否和在多大程度上能够提高系统的性能:
· 系统上的读取/写比例是什么?
· 如果减少读取操作,一个服务器可以多处理多少写负载?
·
网络带宽可满足多少从服务器的需求?
Q:如何使用复制来提供冗余/高可用性?
A:利用目前的可用特性,必须设置一个主服务器和一个从服务器(或多个从服务器),以及写一个脚本来监视主服务器是否启动。如果主服务器失败,通知应用程序和从服务器切换主服务器。下面是一些建议:
· 告知从服务器更改其主服务器,使用CHANGE MASTER TO语句。
· 通知应用程序主服务器位置的一个很好的方法是对主服务器提供动态DNS入口。用bind可以使用nsupdate动态更新DNS。
· 应该用--logs-bin选项而不用 --logs-slave-updates选项运行从服务器。这样,一旦你在其它从服务器上发出STOP SLAVE; RESET MASTER, 以及CHANGE MASTER TO语句,该从服务器可以切换为主服务器。例如,假设有下面的设置:
· WC
· \
· v
· WC----> M
· / | \
· / | \
· v v v
· S1 S2 S3
M代表主服务器,S代表从服务器,WC代表发出数据库写和读取操作的客户;只发出数据库读取操作的客户没有给出,因为它们不需要切换。S1、S2以及S3是从服务器,用--logs-bin选项而没有用--logs-slave-updates运行。因为从服务器收到的主服务器的更新没有记录在二进制日志中,除非指定 --logs-slave-updates选项,每个从服务器上的二进制日志是空的。如果因为某些原因M 变得不可用,你可以选取一个从服务器变为新的主服务器。例如,如果你选取了S1,所有WC应该重新指向S1和S2,并且S3然后应从S1复制。
确保所有从服务器已经处理了中继日志中的所有语句。在每个从服务器上,发出STOP SLAVE IO_THREAD语句,然后检查SHOW PROCESSLIST语句的输出,直到你看到Has read all relay log。当所有从服务器都执行完这些,它们可以被重新配置为一个新的设置。在被提升为主服务器的从服务器S1上,发出STOP SLAVE和RESET MASTER语句。
在其它从服务器S2和S3上,使用STOP SLAVE和CHANGE MASTER TO MASTER_HOST='S1'(其中'S1'表示S1实际的主机名)。为CHANGE MASTER添加关于从S2或S3如何连接到S1的所有信息(user、password、port)。在CHANGE MASTER命令中,不需要指定从其读取的S1的二进制日志名或二进制日志位置:我们知道它是第1个二进制日志,位置是4,这是CHANGE MASTER命令的默认值。最后,在S2和S3上使用START SLAVE 命令。
然后,指示所有WC 把它们的语句指向S1。此后,WC发出的所有发送到S1的更新语句被写入S1的二进制日志,S1则包含M死掉之后的发送到 S1的每一个更新语句。
结果是下面的配置:
WC
/
|
WC | M(unavailable)
\ |
\ |
v v
S1<--S2 S3
^ |
+-------+
当 M重新启动后,你必须在M上发出相同的CHANGE MASTER语句,与在S2和S3上发出的语句一样,以便M变为S1的从服务器并且恢复在它宕机后丢失的所有WC写操作。要把 M 再次作为主服务器(例如,因为它是功能最强的机器),使用前面的步骤,好像S1不可用并且M变为一个新的主服务器一样。在这个过程中,在S1、S2以及S3作为M的从服务器之前,不要忘记在M上运行RESET MASTER。否则,它们可能拾取M变得不可用之前的旧WC写操作。
我们目前正在MySQL集成自动主服务器选择系统,但在准备好之前,你必须创建自己的监控工具。