- 1.恢复被误删的表
- 2.MySQL中为什么既有redo log又有binlog,二者的作用一致吗?
- 3.新创建了一个用户 'xxx'@'%'为什么登不进去
- 4.修改lower_case_table_names 导致的drop database失败
- 5.mysql 远程连接不上,由于bind-address问题
- 6.MySQL中GTID的create table xxx as select 限制和解决方案
- 7.找出锁等待
- 8.为什么InnoDB表要建议用自增列做主键
- 9.为什么生产上建议关闭query cache
- 10.processlist中哪些状态要引起关注
- 11.修改my.cnf配置不生效
- 12.如何将两个表名互换
- 13.Spring框架中调用存储过程失败
- 14.MySQL复制中slave延迟监控
1.恢复被误删的表
前提: mysql开启了bin log日志
1.找到bin log的位置
找到 最近被修改的bin log :master-bin.00000xxx
如果误删除跨越了好几个binlog,那么找回数据的时候就必须一个个的binlog去找回了
2.将这一段时间所有执行的sql语句存入到 待恢复的 sql文件中。
mysqlbinlog --start-date='2017-07-28 19:00:00' --stop-date='2017-07-28 209:00:00' binlog的位置 > restore_20170728.sql
3. 新建一个临时库,在手工去掉 delete 语句之后
source < restore_20170728.sql
4.将恢复的表source回原库
2.MySQL中为什么既有redo log又有binlog,二者的作用一致吗?
binlog 是Server层记录的日志,主要用于复制(replication),记录的是DML操作的日志。 redo log是innodb存储引擎的日志,记录的也是DML操作的变化,但二者的格式不一样。在事务提交前,只要将Redo Log持久化即可,不需要将数据持久化。当系统崩溃时,虽然数据没有持久化,但是RedoLog已经持久化。系统可以根据RedoLog的内容,将所有数据恢复到最新的状态。 binlog适用于多个存储引擎,而redo/undo是innodb特有的。 顺便提一下,redo用于重做(保证事务的持久性),undo用于回滚(保证事务的原子性)、mvcc,还有一句绕口的:undo 也会产生 redo 来保证undo log的可靠性。
3.新创建了一个用户 'xxx'@'%'为什么登不进去
[root@nazeebo softdb]# mysql -ubkadmin -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'bkadmin'@'localhost' (using password: YES)
[root@nazeebo softdb]# mysql -uroot -p123456
mysql> select Host,user from mysql.user;
+-------------+-------------------+
| Host | user |
+-------------+-------------------+
| % | bkadmin |
| % | nainai |
| % | root |
| % | select_role_group |
| % | sure |
| % | system |
| % | yeye |
| 127.0.0.1 | nazeebo |
| 127.0.0.1 | root |
| 192.168.0.% | lowa |
| ::1 | root |
| localhost | |
| localhost | mysql.session |
| localhost | mysql.sys |
| localhost | root |
| nazeebo | |
| nazeebo | root |
+-------------+-------------------+
drop 掉 ''@'localhost'可以正常登入
mysql> drop user ''@'localhost';
Query OK, 0 rows affected (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.01 sec)
[root@nazeebo softdb]# mysql -ubkadmin -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 56
Server version: 5.7.22-log MySQL Community Server (GPL)
Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
4.修改lower_case_table_names 导致的drop database失败
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| employees |
| mysql |
| performance_schema |
| sbtest |
| sys |
| test |
| test_lowa |
| tpcc1 |
+--------------------+
9 rows in set (0.00 sec)
mysql> drop database tpcc1;
ERROR 1010 (HY000): Error dropping database (can't rmdir './tpcc1', errno: 39)
问题分析
mysqld 在执行 drop database 操作的时候,是调用 mysql_rm_db
这个函数,在删除时先把db下的所有表都删掉,然后再把db删掉。为了找出对应db下的所有表,mysqld 是通过遍历数据库目录下的文件来做的,具体是用 find_db_tables_and_rm_known_files
这个函数,遍历数据库目录下的所有文件,然后构造出要 drop 的table列表,然而在构造删除列表过程中,会有这样一个判断:
if (lower_case_table_names)
table_list->table_name_length= my_casedn_str(files_charset_info,
table_list->table_name);
意思就是如果lower_case_table_names
非0的话,就把 table_name 转成小写的,
在list表都删除完后,调用rm_dir_w_symlink
来删除db目录,此时tpcc目录下还有对应的文件,这个函数会调用系统的 rmdir 函数,而当目录非空的时候,rmdir是执行失败的。
所以我们看到最终的错误提示 Error dropping database (can't rmdir './db1', errno: 39)
5.mysql 远程连接不上,由于bind-address问题
刚安装了mysql服务器,使用远程管理工具总是连接不上
还是连接不上,于是怀疑是防火墙问题,便将防火墙关service iptables stop
再次telnet,还是没办法连上这个端口,然后通过netstat查看3306的端口状态是怎么样的
netstat -apn|grep 3360
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN 3783/mysqld
终于发现了一个比较奇怪的东西,注意127.0.0.1:3306
这一列。监听端口正常,但却绑定了本地回旋地址,难怪总是连接不上。
修改mysql的配置文件/etc/my.conf,将bind-address后面增加远程访问IP地址或者禁掉这句话就可以让远程机登陆访问了。
修改参数后要重启mysql服务service mysql restart
6.MySQL中GTID的create table xxx as select 限制和解决方案
比如MySQL GTID在5.6试水,5.7已经发展完善,但是还是有一些场景是受限的。比如最常用的一个语句:
- create table xxx as select 的模式
GTID中create 语句限制的解法:
create table xxx as select的语句,其实会被拆分为两部分,create
语句和insert
语句,但是如果想一次搞定,MySQL会抛出如下的错误。
mysql> create table test_new as select *from test;
ERROR 1786 (HY000): Statement violates GTID consistency: CREATE TABLE ... SELECT.
一个方法是MySQL特有的用法 like!
create table xxx as select
的方式会被拆分成两部分。
create table xxxx like data_mgr;
+ insert into xxxx select *from data_mgr;
7.找出锁等待
服务器级别的锁等待
可以通过show processlist看到等待锁的线程id,但是无法知道究竟哪个线程持有锁 可以通过mysqladmin debug 相关等待锁的线程以及谁持有锁可以在错误日志中找到
存储引擎innodb中锁等待以及哪个线程持有锁
SELECT r.trx_id AS waiting_trx_id, r.trx_mysql_thread_id AS waiting_thread, TIMESTAMPDIFF(SECOND, r.trx_wait_started, CURRENT_TIMESTAMP) AS wait_time, r.trx_query AS waiting_query, l.lock_table AS waiting_table_lock, b.trx_id AS blocking_trx_id, b.trx_mysql_thread_id AS blocking_thread, SUBSTRING(p.host,1,INSTR(p.host, ':') -1 ) AS blocking_host, SUBSTRING(p.host, INSTR(p.host, ':') +1 ) AS block_port, IF(p.command="Sleep",p.time,0) AS idle_in_trx, b.trx_query AS blcoking_query from information_schema.innodb_lock_waits AS w INNER JOIN information_schema.innodb_trx AS b ON b.trx_id=w.blocking_trx_id INNER JOIN information_schema.innodb_trx AS r ON r.trx_id = w.requesting_trx_id INNER JOIN information_schema.innodb_locks AS l ON w.requested_lock_id = l.lock_id LEFT JOIN information_schema.processlist AS p ON p.id = b.trx_mysql_thread_id ORDER BY wait_time DESC\G
查询有多少查询被哪些线程阻塞
如果因为线程在一个事务中空闲而正在遭受大量的锁操作,下面查询显示存储引擎层有多少查询被哪些线程阻塞。
SELECT CONCAT('thread ', b.trx_mysql_thread_id, ' from ',p.host) AS who_blocks, IF (p.command = "Sleep",p.time, 0) AS idle_in_trx, MAX(TIMESTAMPDIFF(SECOND,r.trx_wait_started,NOW())) AS max_wait_time, COUNT(*) AS num_waiters FROM information_schema.innodb_lock_waits as w inner join information_schema.innodb_trx as b on b.trx_id = w.blocking_trx_id inner join information_schema.innodb_trx as r on r.trx_id = w.requesting_trx_id left join information_schema.processlist as p on p.id = b.trx_mysql_thread_id group by who_blocks order by num_waiters desc\G
8.为什么InnoDB表要建议用自增列做主键
InnoDB引擎表的一些关键特征:
- InnoDB引擎表是基于B+树的索引组织表(IOT);
- 每个表都需要有一个聚集索引(clustered index);
- 所有的行记录都存储在B+树的叶子节点(leaf pages of the tree);
- 基于聚集索引的增、删、改、查的效率相对是最高的;
- 如果我们定义了主键(PRIMARY KEY),那么InnoDB会选择其作为聚集索引;
- 如果没有显式定义主键,则InnoDB会选择第一个不包含有NULL值的唯一索引作为主键索引;
- 如果也没有这样的唯一索引,则InnoDB会选择内置6字节长的ROWID作为隐含的聚集索引(ROWID随着行记录的写入而主键递增,这个ROWID不像ORACLE的ROWID那样可引用,是隐含的)。
综上总结,如果InnoDB表的数据写入顺序能和B+树索引的叶子节点顺序一致的话,这时候存取效率是最高的,也就是下面这几种情况的存取效率最高:
- 使用自增列(INT/BIGINT类型)做主键,这时候写入顺序是自增的,和B+数叶子节点分裂顺序一致;
- 该表不指定自增列做主键,同时也没有可以被选为主键的唯一索引(上面的条件),这时候InnoDB会选择内置的ROWID作为主键,写入顺序和ROWID增长顺序一致;
- 除此以外,如果一个InnoDB表又没有显示主键,又有可以被选择为主键的唯一索引,但该唯一索引可能不是递增关系时(例如字符串、UUID、多字段联合唯一索引的情况),该表的存取效率就会比较差。
实际情况是如何呢?经过简单TPCC基准测试,修改为使用自增列作为主键与原始表结构分别进行TPCC测试,前者的TpmC结果比后者高9%倍,足见使用自增列做InnoDB表主键的明显好处,其他更多不同场景下使用自增列的性能提升可以自行对比测试下。
9.为什么生产上建议关闭query cache
Query Cache(查询缓存,以下简称QC)存储SELECT语句及其产生的数据结果,特别适用于:频繁提交同一个语句,并且该表数据变化不是很频繁的场景,例如一些静态页面,或者页面中的某块不经常发生变化的信息。QC有可能会从InnoDB Buffer Pool或者MyISAM key buffer里读取结果。
由于QC需要缓存最新数据结果,因此表数据发生任何变化(INSERT、UPDATE、DELETE或其他可能产生数据变化的操作),都会导致QC被刷新。
根据MySQL官方的测试,QC的优劣分别是:
1、如果对一个表执行简单的查询,但每次查询都不一样的话,打开QC后,性能反而下降了13%左右。但通常实际业务中,通常不会只有这种请求,因此实际影响应该比这个小一些。 2、如果对一个只有一行数据的表进行查询,则可以提升238%,这个效果还是非常不错的。
因此,如果是在一个更新频率非常低而只读查询频率非常高的场景下,打开QC还是比较有优势的,其他场景下,则不建议使用。而且,QC一般也维持在100MB以内就够了,没必要设置超过数百MB。
QC严格要求2次SQL请求要完全一样,包括SQL语句,连接的数据库、协议版本、字符集等因素都会影响,下面几个例子中的SQL会被认为是完全不一样而不会使用同一个QC内存块:
mysql> set names latin1; SELECT * FROM table_name;
mysql> set names latin1; select * from table_name;
mysql> set names utf8; select * from table_name;
此外,QC也不适用于下面几个场景:
- 子查询或者外层查询;
- 存储过程、存储函数、触发器、event中调用的SQL,或者引用到这些结果的;
- 包含一些特殊函数时,例如:BENCHMARK()、CURDATE()、CURRENT_TIMESTAMP()、NOW()、RAND()、UUID()等等;
- 读取mysql、INFORMATION_SCHEMA、performance_schema 库数据的;
- 类似SELECT…LOCK IN SHARE MODE、SELECT…FOR UPDATE、SELECT..INTO OUTFILE/DUMPFILE、SELECT..WHRE…IS NULL等语句;
- SELECT执行计划用到临时表(TEMPORARY TABLE);
- 未引用任何表的查询,例如 SELECT 1+1 这种;
- 产生了 warnings 的查询;
- SELECT语句里加了 SQL_NO_CACHE 关键字;
更加奇葩的是,MySQL在从QC中取回结果前,会先判断执行SQL的用户是否有全部库、表的SELECT权限,如果没有,则也不会使用QC。
相比下面这个,其实上面所说的都不重要。
最为重要的是,在MySQL里QC是由一个全局锁在控制,每次更新QC的内存块都需要进行锁定。 例如,一次查询结果是20KB,当前 query_cache_min_res_unit 值设置为 4KB(默认值就是4KB,可调整),那么么本次查询结果共需要分为5次写入QC,每次都要锁定,可见其成本有多高。
我们可以通过 PROFILING 功能来查看 QC 相关的一些锁竞争,例如像下面这样的:
• Waiting for query cache lock
• Waiting on query cache mutex
或者,也可以通过执行 SHOW PROCESSLIST
来看线程的状态,例如:
checking privileges on cached query
检查用户是否有权限读取QC中的结果集
checking query cache for query
检查本次查询结果是否已经存储在QC中
invalidating query cache entries
由于相关表数据已经修改了,因此将QC中的内存记录被标记为失效
sending cached result to client
从QC中,将缓存后的结果返回给客户程序
storing result in query cache
将查询结果缓存到QC中
如果可以频繁看到上述几种状态,那么说明当前QC基本存在比较重的竞争。
以上那么多,总结一下其实核心要点就一个: 如果线上环境中99%以上都是只读,很少有更新,再考虑开启QC吧,否则,就别开了。 关闭方法很简单,有两种:
- 同时设置选项 query_cache_type = 0 和 query_cache_size = 0;
- 如果用源码编译MySQL的话,编译时增加参数 --without-query-cache 即可;
10.processlist中哪些状态要引起关注
状态 | 建议 |
---|---|
copy to tmp table | 执行ALTER TABLE修改表结构时建议:放在凌晨执行或者采用类似pt-osc工具 |
Copying to tmp table | 拷贝数据到内存中的临时表,常见于GROUP BY操作时建议:创建适当的索引 |
Copying to tmp table on disk | 临时结果集太大,内存中放不下,需要将内存中的临时表拷贝到磁盘上,形成 sql***.MYD 、sql***.MYI (在5.6及更高的版本,临时表可以改成InnoDB引擎了,可以参考选项default_tmp_storage_engine )建议:创建适当的索引,并且适当加大sort_buffer_size /tmp_table_size /max_heap_table_size |
Creating sort index | 当前的SELECT中需要用到临时表在进行ORDER BY排序建议:创建适当的索引 |
Creating tmp table | 创建基于内存或磁盘的临时表,当从内存转成磁盘的临时表时,状态会变成:Copying to tmp table on disk建议:创建适当的索引,或者少用UNION、视图(VIEW)、子查询(SUBQUERY)之类的,确实需要用到临时表的时候,可以在session级临时适当调大 tmp_table_size/max_heap_table_size 的值 |
Reading from net | 表示server端正通过网络读取客户端发送过来的请求建议:减小客户端发送数据包大小,提高网络带宽/质量 |
Sending data | 从server端发送数据到客户端,也有可能是接收存储引擎层返回的数据,再发送给客户端,数据量很大时尤其经常能看见备注:Sending Data不是网络发送,是从硬盘读取,发送到网络是Writing to net(建议:通过索引或加上LIMIT,减少需要扫描并且发送给客户端的数据量) |
Sorting result | 正在对结果进行排序,类似Creating sort index,不过是正常表,而不是在内存表中进行排序建议:创建适当的索引 |
statistics | 进行数据统计以便解析执行计划,如果状态比较经常出现,有可能是磁盘IO性能很差建议:查看当前io性能状态,例如iowait |
Waiting for global read lock | FLUSH TABLES WITH READ LOCK整等待全局读锁建议:不要对线上业务数据库加上全局读锁,通常是备份引起,可以放在业务低谷期间执行或者放在slave服务器上执行备份 |
Waiting for tables,Waiting for table flush | FLUSH TABLES, ALTER TABLE, RENAME TABLE, REPAIR TABLE, ANALYZE TABLE, OPTIMIZE TABLE等需要刷新表结构并重新打开建议:不要对线上业务数据库执行这些操作,可以放在业务低谷期间执行 |
Waiting for lock_type lock | 等待各种类型的锁:• Waiting for event metadata lock• Waiting for global read lock • Waiting for schema metadata lock• Waiting for stored function metadata lock• Waiting for stored procedure metadata lock• Waiting for table level lock• Waiting for table metadata lock• Waiting for trigger metadata lock建议:比较常见的是上面提到的global read lock以及table metadata lock,建议不要对线上业务数据库执行这些操作,可以放在业务低谷期间执行。如果是table level lock,通常是因为还在使用MyISAM引擎表,赶紧转投InnoDB引擎吧,别再老顽固了 |
11.修改my.cnf配置不生效
问题
修改了 my.cnf 配置文件后,却不生效,这是怎么回事?
原因
我们注意到,这里只说了修改 my.cnf,并没有说清楚其绝对路径是哪个文件。也就是说,有可能修改的不是正确路径下的my.cnf文件。
在MySQL中,是允许存在多个 my.cnf 配置文件的,有的能对整个系统环境产生影响,例如:/etc/my.cnf。有的则只能影响个别用户,例如:~/.my.cnf。
MySQL读取各个my.cnf配置文件的先后顺序是:
- /etc/my.cnf
- /etc/mysql/my.cnf
- /usr/local/mysql/etc/my.cnf
- ~/.my.cnf
- 其他自定义路径下的my.cnf,例如:/data/mysql/yejr_3306/my.cnf
不管是mysqld服务器端程序,还是mysql客户端程序,都可以采用下面两个参数来自行指定要读取的配置文件路径:
- –defaults-file=#, 只读取指定的文件(不再读取其他配置文件)
- –defaults-extra-file=#, 从其他优先级更高的配置文件中读取全局配置后,再读取指定的配置文件(有些选项可以覆盖掉全局配置从的设定值)
因此,可以看到,如果修改的是非“著名”目录下的 my.cnf,有可能看起来是不生效的,需要自行指定,或者统一放在 /etc/my.cnf 下,采用多实例的方式来管理即可。
12.如何将两个表名互换
从MySQL手册里能找到方法:同时锁定2个表,不允许写入,然后对调表名。
LOCK TABLES t1 WRITE, t2 WRITE;
ALTER TABLE t1 RENAME TO t3;
ALTER TABLE t2 RENAME TO t1;
ALTER TABLE t3 RENAME TO t2;
UNLOCK TABLES;
13.Spring框架中调用存储过程失败
Spring框架中,调用存储过程同时还需要show create procedure权限,对于普通用户而言,还要授予 select on mysql.proc 权限才能正常
14.MySQL复制中slave延迟监控
在MySQL复制环境中,我们通常只根据 Seconds_Behind_Master 的值来判断SLAVE的延迟。这么做大部分情况下尚可接受,但并不够准确,而应该考虑更多因素。 首先,我们先看下SLAVE的状态:
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
***
Master_Log_File: mysql-bin.000327
Read_Master_Log_Pos: 668711237
Relay_Log_File: mysql-relay-bin.002999
Relay_Log_Pos: 214736858
Relay_Master_Log_File: mysql-bin.000327
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
***
Skip_Counter: 0
Exec_Master_Log_Pos: 654409041
Relay_Log_Space: 229039311
***
Seconds_Behind_Master: 3296
***
可以看到 Seconds_Behind_Master 的值是 3296,也就是SLAVE至少延迟了 3296 秒。
再来看下SLAVE上的2个REPLICATION进程状态:
mysql> show full processlist\G
*************************** 1. row ***************************
Id: 6
User: system user
Host:
db: NULL
Command: Connect
Time: 22005006
State: Waiting for master to send event
Info: NULL
*************************** 2. row ***************************
Id: 7
User: system user
Host:
db: NULL
Command: Connect
Time: 3293
State: Updating
Info: UPDATE ** SET ** WHERE **
可以看到SQL线程一直在执行UPDATE操作,注意到 Time 的值是 3293,看起来像是这个UPDATE操作执行了3293秒,一个普通的SQL而已,肯定不至于需要这么久。 实际上,在REPLICATION进程中,Time 这列的值可能有几种情况:
- SQL线程当前执行的binlog(实际上是relay log)中的timestamp和IO线程最新的timestamp的差值,这就是通常大家认为的 Seconds_Behind_Master 值,并不是某个SQL的实际执行耗时;
- SQL线程当前如果没有活跃SQL在执行的话,Time值就是SQL线程的idle time;
而IO线程的Time值则是该线程自从启动以来的总时长(多少秒),如果系统时间在IO线程启动后发生修改的话,可能会导致该Time值异常,比如变成负数,或者非常大。
来看下面几个状态:
#设置pager,只查看关注的几个status值
mysql> pager cat | egrep -i 'system user|Exec_Master_Log_Pos|Seconds_Behind_Master|Read_Master_Log_Pos'
#这是没有活跃SQL的情况,Time值是idle time,并且 Seconds_Behind_Master 为 0
mysql> show processlist; show slave status\G
| 6 | system user | | NULL | Connect | 22004245 | Waiting for master to send event | NULL |
| 7 | system user | | NULL | Connect | 13 | Has read all relay log;**
Read_Master_Log_Pos: 445167889
Exec_Master_Log_Pos: 445167889
Seconds_Behind_Master: 0
#和上面一样
mysql> show processlist; show slave status\G
| 6 | system user | | NULL | Connect | 22004248 | Waiting for master to send event | NULL |
| 7 | system user | | NULL | Connect | 16 | Has read all relay log;**
Read_Master_Log_Pos: 445167889
Exec_Master_Log_Pos: 445167889
Seconds_Behind_Master: 0
#这时有活跃SQL了,Time值是和 Seconds_Behind_Master 一样,即SQL线程比IO线程“慢”了1秒
mysql> show processlist; show slave status\G
| 6 | system user | | NULL | Connect | 22004252 | Waiting for master to send event | NULL |
| 7 | system user | | floweradmin | Connect | 1 | Updating | update **
Read_Master_Log_Pos: 445182239
Exec_Master_Log_Pos: 445175263
Seconds_Behind_Master: 1
#和上面一样
mysql> show processlist; show slave status\G
| 6 | system user | | NULL | Connect | 22004254 | Waiting for master to send event | NULL |
| 7 | system user | | floweradmin | Connect | 1 | Updating | update **
Read_Master_Log_Pos: 445207174
Exec_Master_Log_Pos: 445196837
Seconds_Behind_Master: 1
最后我们如何正确判断SLAVE的延迟情况:
- 首先看
Relay_Master_Log_File
和Master_Log_File
是否有差异; - 如果
Relay_Master_Log_File
和Master_Log_File
是一样的话,再来看Exec_Master_Log_Pos
和Read_Master_Log_Pos
的差异,对比SQL线程比IO线程慢了多少个binlog事件; - 如果
Relay_Master_Log_File
和Master_Log_File
不一样,那说明延迟可能较大,需要从MASTER上取得binlog status,判断当前的binlog和MASTER上的差距;
因此,相对更加严谨的做法是:
在第三方监控节点上,对MASTER和SLAVE同时发起SHOW BINARY LOGS和SHOW SLAVE STATUS\G
的请求,最后判断二者binlog的差异,以及 Exec_Master_Log_Pos
和 Read_Master_Log_Pos
的差异。
例如: 在MASTER上执行SHOW BINARY LOGS 的结果是:
+------------------+--------------+
| Log_name | File_size |
+------------------+--------------+
| mysql-bin.000009 | 1073742063 |
| mysql-bin.000010 | 107374193 |
+------------------+--------------+
而在SLAVE上执行SHOW SLAVE STATUS\G 的结果是:
Master_Log_File: mysql-bin.000009
Read_Master_Log_Pos: 668711237
Relay_Master_Log_File: mysql-bin.000009
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
***
Exec_Master_Log_Pos: 654409041
***
Seconds_Behind_Master: 3296
***
这时候,SLAVE实际的延迟应该是: mysql-bin.000009 这个binlog中的binlog position 1073742063 和 SLAVE上读取到的binlog position之间的差异延迟,即:
1073742063 - 654409041 = 419333022 个binlog event
并且还要加上 mysql-bin.000010这个binlog已经产生的107374193个binlog event,共
107374193 + 419333022 = 526707215 个binlog event