mysql>grant replication slave on *.* to 'backup'@'%' identified by 'password';
mysql>use bbs;
mysql>flush tables with read lock;

mysql> show master status;

+------------------+----------+--------------+------------------+

| File              | Position | Binlog_Do_DB | Binlog_Ignore_DB |

+------------------+----------+--------------+------------------+

| mysql-bin.000001 |        98 | bbs           |                   |

+------------------+----------+--------------+------------------+

1 row in set (0.00 sec)

File列显示日志名,而Position显示偏移量。在该例子中,二进制日志值为mysql-bin.000001,偏移量为98。记录该值。以后设置从服务器时需要使用这些值。它们表示复制坐标,从服务器应从该点(也可以是任何点)开始从主服务器上进行新的更新。


此时不要关闭此终端!

注意:为了保证FLUSH TABLES语句让读锁定保持有效。(如果退出客户程序,锁被释放)。建立新的SSH连接,然后对主服务器上的数据进行快照。

记住上表前两个字段的信息 mysql-bin.000001 和 98 。
另开一个终端:

4. 建立快照
拿到主数据库上的“数据库快照”

Cd /var/lib/mysql

tar -cvf /tmp/mysql-snapshot.tar ./bbs
数据库大怎么办?用mysqldump导出。
本例:tar -cvf /tmp/mysql-snapshot.tar ./bbs --其中的一个数据库,其它的无关紧要。

5. 解锁

mysql > UNLOCK TABLES;    #让master正常更新数据库



主服务器上的相关命令:
show master status
show slave hosts
show logs
show binlog events
purge logs to 'log_name'
purge logs before 'date'
reset master(老版本flush master)
set sql_log_bin=


从服务器上的相关命令:
slave start
slave stop
SLAVE STOP IO_THREAD //此线程把master段的日志写到本地
SLAVE start IO_THREAD
SLAVE STOP SQL_THREAD //此线程把写到本地的日志应用于数据库
SLAVE start SQL_THREAD
reset slave
SET GLOBAL SQL_SLAVE_SKIP_COUNTER
load data from master
show slave status(SUPER,REPLICATION CLIENT)
CHANGE MASTER TO MASTER_HOST=, MASTER_PORT=,MASTER_USER=, MASTER_PASSWORD= //动态改变master信息
PURGE MASTER [before 'date'] 删除master端已同步过的日志


slave-skip-errors=1007,1051,1062 #跳过的错误号

1.马上进入从库
stop slave;
set global sql_slave_skip_counter=1; (1是指跳过一个错误)
slave start;

修改从库的/etc/my.cnf文件
在里面的[mysqld]下面加入了一行
slave-skip-errors = 1062(忽略所有的1062错误)
重启下从库的mysql /etc/init.d/mysqld restart

show slave status \G;一下发现正常了,但是我知道这时的数据可能已经不同步了,
再次查看一下日志,让我感到意外的是tail -f mysql_error.log出现大量的
.......
100106 16:54:21 [Warning] Statement may not be safe to log in statement format. Statement: delete from `system_message_1` where `to_uid` = 181464 ORDER BY `id` ASC LIMIT 1

.........
日志里面有大量的这种警告,意思应该是statement 格式不安全,用vim 打开他看了一下,发现好多这类警告,我说为什么错误日志怎么变这么大了呢!!
statement format应该是 binlog的一种格式,进入从库查看一下
show global variables like 'binlog_format';
果然当前的格式为statement

我需要把格式改为mixed格式
修改从库的 my.cfg
[mysqld]下面加入下面这行
binlog_format=mixed

然后重启mysql服务,发现错误日志里的 警告 都停止了


2. Mysql主从同步延迟与系统时间的关系

SELECT UNIX_TIMESTAMP()

在有分歧的情况下, 去查看了一下Mysql的源代码, 结果发现手册上的描述居然不那么准确, 代码大致如下:
......if ((mi->slave_running ==MYSQL_SLAVE_RUN_CONNECT)&&mi->rli.slave_running){

long time_diff= ((long)(time(0) -mi->rli.last_master_timestamp) -mi->clock_diff_with_master);
protocol->store((longlong)(mi->rli.last_master_timestamp? max(0, time_diff) :0));
......}else{
protocol->store_null();
}
从代码看, 如果从库IO线程到主库的连接有问题或者SQL线程没有在运行, Seconds_Behind_Master直接返回NULL;否则的话,用从库当前系统时间减去IO线程处理的最近的事件的时间戳;代码里用mi->clock_diff_with_master来排除系统时间差对计算的影响,那这个值又是怎么计算来的呢? 继续看代码:

......if (!mysql_real_query(mysql, STRING_WITH_LEN("SELECTUNIX_TIMESTAMP()")) &&(master_res=mysql_store_result(mysql))&&(master_row=mysql_fetch_row(master_res))){ mi->clock_diff_with_master= (long) (time((time_t*) 0) -strtoul(master_row[0], 0, 10));}else if(!check_io_slave_killed(mi->io_thd, mi,NULL)){ mi->clock_diff_with_master= 0; ......}

原来这个值是通过在主库上执行SELECT UNIX_TIMESTAMP()来取得主库的系统时间,然后去减从库的当前系统时间。

原来系统时间差还真的对主从同步延迟参数Seconds_Behind_Master有影响。



binlog日志是可以按策略自动删除的
在my.cnf 配置下面2个参数即可

expire_logs_days
max_binlog_size


我都是使用命令删除binlog的
//删除所有binlog日志,新日志编号从头开始
mysql>RESET MASTER;
删除log_name之前的日志
mysql>PURGE {MASTER | BINARY} LOGS TO 'log_name'
删除data之前的日志
mysql>PURGE {MASTER | BINARY} LOGS BEFORE 'date'