MySQL -- 故障诊断
SELECT 1
SELECT 1只能说明数据库进程还在,但不能说明数据库没有问题
1 | -- innodb_thread_concurrency表示并发线程数量 |
表初始化
1 | -- innodb_thread_concurrency默认为0,表示不限制并发线程数量,建议设置范围64~128 |
操作序列
| session A | session B | session C | session D |
|---|---|---|---|
| SELECT SLEEP(100) FROM t; | SELECT SLEEP(100) FROM t; | SELECT SLEEP(100) FROM t; | |
| SELECT 1; (Query OK) |
|||
| SELECT * FROM t; (Blocked) |
并发线程达到上限3后,InnoDB在接收新请求时,会进入等待状态
并发连接 VS 并发查询
SHOW PROCESSLIST可能会看到几千个连接,指的是并发连接;而当前正在执行的语句,才是并发查询- 并发连接达到几千影响并不大,无非就是多占用一些内存,
- 并发查询太大才是CPU杀手,因此才需要设置
innodb_thread_concurrency
- 并发查询太大才是CPU杀手,因此才需要设置
- 在线程进入锁等待后,并发线程的计数将会减一
- 等待行锁或间隙锁的线程不属于并发线程,因为这些线程不会再消耗CPU
SELECT SLEEP(100) FROM t是在真正地执行查询,所以还是要算并发线程
查询判断
- 在系统库(
mysql)里建一个表,命名为health_check,里面只放一行数据,然后定期查询SELECT * FROM mysql.health_check- 可以检测出由于并发线程过多而导致数据库不可用的情况
- 但该方法无法检测磁盘空间满的情况
- 更新事务需要写
binlog,而一旦binlog所在磁盘的空间占用率达到率100% - 所有的更新语句和事务的commit语句都会被阻塞
- 但此时系统还是可以正常地读取数据的
- 更新事务需要写
更新判断
UPDATE mysql.health_check SET t_modified=now()- 主库和从库都需要进行节点的可用性检测,从库的可用性检测也是需要写
binlog的 - 一般会把A和B的主从关系设计为
Master-Master结构,在从库B上执行的检测命令,也会发回主库A - 如果主库A和从库B都使用相同的更新命令,可能会出现行冲突(无法区分谁更新的),导致主从同步停止
- 为了主从之间的更新不产生冲突,在
mysql.health_check上存入多行数据,server_id为主键 - MySQL规定主库和从库的
server_id必须不同,从而保证主从各自的检测命令不会发生冲突
- 为了主从之间的更新不产生冲突,在
1 | CREATE TABLE `health_check` ( |
判定慢
- 所有的检测都需要一个超时时间N,执行一个
UPDATE语句,如果超过N秒后不返回,会认为系统不可用 - 假设一个日志盘的IO利用率已经是100%,整个系统响应非常慢,已经准备做主从切换了
- IO利用率为100%,表示系统的IO在正常工作,每个请求都是有机会得到IO资源的
- 而检测使用的
UPDATE命令,需要的资源是很少的- 可能在N秒内返回给检测系统,检测系统误认为系统是正常的
- 表现:业务系统上正常的SQL执行很慢,但DBA在HA系统上看到的却是系统处于可用状态
- 根本原因:都是基于外部检测(定时轮询),天然存在随机性的问题
内部统计
redolog
1 | mysql> SELECT * FROM performance_schema.file_summary_by_event_name WHERE EVENT_NAME='wait/io/file/innodb/innodb_log_file'\G; |
EVENT_NAME:统计的类型,这里为redolog- 第1组:
COUNT_STAR~`MAX_TIMER_WAIT,所有IO类型的统计,单位为皮秒,1 PS = 10^-12 S` - 第2组:
COUNT_READ~`SUM_NUMBER_OF_BYTES_READ`,读操作的统计SUM_NUMBER_OF_BYTES_READ:总共从redolog读取了多少字节
- 第3组:
COUNT_WRITE~`SUM_NUMBER_OF_BYTES_WRITE`,写操作的统计 - 第4组:
COUNT_MISC~`MAX_TIMER_MISC`,其它类型数据的统计- 在
redolog里,可以理解为对fsync的统计
- 在
binlog
1 | mysql> SELECT * FROM performance_schema.file_summary_by_event_name WHERE EVENT_NAME='wait/io/file/sql/binlog'\G; |
性能损耗
如果打开所有的performance_schema,性能大概会下降10%左右,建议只打开所需要的项
1 | UPDATE setup_instruments SET ENABLED='YES', TIMED='YES' WHERE NAME LIKE '%wait/io/file/innodb/innodb_log_file%'; |
故障诊断
假设已经开启了redolog和binlog的统计信息功能,可以通过MAX_TIMER来判断数据库是否有问题
1 | -- 单次IO超过200ms |
参考资料
《MySQL实战45讲》
All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.









