高性能mysql附录A-笔记-mysql分支
mysql的三个分支(变种):
- Percona Server: 透明、性能、灵活,用XtraDB引擎代替innodb;
- MariaDB: mysql原作者。面向客户、补丁插件扩展更多;
- Drizzle:sql语法不兼容mysql, 修正bug,最开源。
官方mysql: 最接近于Percona Server。
高性能mysql附录B-笔记-服务器状态
系统变量: show variables like '%xxx%'
;
只读状态: show status like '%xxx%'
; 或infomation_schema.global_status
表和information_schama.session_status
表;
其他信息:infomation_schema
库中
线程和连接统计
1 | connections,max_used_connections,threads_connected |
二进制日志状态
1 | binlog_cache_use,binlog_cache_disk_use |
命令计数器
Com_*
变量统计每种类型的SQL或C API命令发起过的次数。
1 | Com_select: select语句的数量; |
临时文件和表
隐式表和文件:
1 | show global status like 'Created_tmp%' |
显式临时表:
1 | show global temporary tables; |
查看select查询类型统计
1 | show global status like 'Select%'; |
按预期次数从多到少/开销从少到多的顺序:
Select_range: 在第一个表上扫描一个索引区间的连接数目;
Select_scan: 扫描整个第一个表;
Select_full_range_join: 开销多于Select_scan;
Select_range_check: 开销非常高;
Select_full_join: 开销最高。
表锁
Table_locks_immediate: 立即授权的表锁次数;
Table_locks_waited: 需要等待的表锁次数。
innodb状态
查看innodb相关的状态开销很大,会创建一个全局锁。
1 | 1. 通过show engine innodb status; |
因此不能频繁查看这些变量。
输出信息包括:
- fsync()平均每秒调用次数;
- 头部信息: 时间;
- Semaphores: 操作系统等待数组,等待互斥量的innodb线程;(如果有等待,可以看出热点是什么)
1
2
3waited at buf0buf.ic for 0 second: 等待缓冲区
waiters flag 0: 0个线程在等待;
waiting is ending: 等待结束。
innodb_sync_spin_loops
变量:
空转多少次后停止spin,挂起进入真正等待。
1 | show variables like '%spin%'; |
死锁
SHOW ENGINE INNODB STATUS\G
的输出还有一部分是上两次死锁的情况。(包括进程id和sql、等待的是什么锁)
死锁类型:
- 循环等待;
- 等待关系图太深:
(1)检查超过100W个锁;
(2)重做超过200个事务。
错误信息:”TOO DEEP OR LONG SEARCH IN THE LOCK TABLE WAITS-FOR GRAPH”.
减少死锁的TIPS
在事务里更新数据时,先按主键排序,这样扫描索引的顺序就都是一致的;
事务信息
SHOW ENGINE INNODB STATUS\G
的输出里还有一部分是事务总结信息和当前活跃事务信息。
事务总结信息
- 当前事务ID;
- 已经清理MVCC行的事务ID;(可以知道有多少老版本数据没被清理)
- 历史记录的长度;
- 锁结构的数目(可能包含多个行锁)。
活跃事务信息
- 进程id(与
show processlist
中id通用) - 内部查询号;
- 连接信息
- 查询的sql。
File I/O
SHOW ENGINE INNODB STATUS\G
的输出里还有一部分是IO辅助线程的状态和性能计数器的状态。
其中:
1 | insert buffer thread: 插入缓冲合并到表空间; |
redo log统计
SHOW ENGINE INNODB STATUS\G
的输出里还有一部分是事务日志(redo log)的统计。
- sequence number: 当前日志序号;
- flushed up to : 当前刷到哪里;
- last checkpoint: 上一个检测点的位置。
- pending和done的日志操作数量。
缓冲池和内存
SHOW ENGINE INNODB STATUS\G
的输出里还有一部分是BufferPool和内存统计。
包括信息:
- 分配了多少字节;
- pool总共多少页,其中free多少页;
- database用了多少页,多少页已经修改;
- 命中率等统计信息。
多个缓冲池的话后头还有各个buffer pool各自的统计信息。
ROW OPERATIONS
SHOW ENGINE INNODB STATUS\G
的输出里最后一部分是行操作统计。
1 | -------------- |
包括信息:
- 多少线程在innodb内核内,多少在等待队列;
- 累积增删改查;
- 增删改查的瞬时速度。
主备相关查看命令
1 | show master status \G |
Information_schema中的innodb信息表
innodb_trx,innodb_locks
事务、拥有和等待锁的事务。
performance_schema
略
高性能mysql附录C-笔记-大文件传输
大概是ssh,tar,gz,rsync命令的运用,略。
高性能mysql附录E-笔记-explain
explain语句:
explain select xxx
: 近似的执行计划信息;- 近似的执行计划信息+等效sql:
1
2explain extended select xxx;
show warnings; -- 这里得到的sql是从执行计划反向翻译过来的sql explain partitions select xxx
: 显示查询的分区。(仅对分区表有效)
mysql5.6前,explain的时候会执行子查询创建临时表,以便进行外层优化。
explain各列的含义
id
select语句顺序编号,对应在原始语句中的位置;(从外到内)
select的三种类型:
- 简单子查询;
- 复杂子查询(派生表);
- union查询。
其中union查询的id列为null,select_type列为union result
。
select_type列
取值含义:
1 | simple: 简单查询; |
table列
访问的表或别名。
或者< derivedN>,其中N是子查询的id。
union行中table列出现的< union2,3>其中2,3也是子查询的id。
type列
访问类型:从差到好:
1 | all: 扫全表 |
possible_keys列
优化早期尝试的索引,可能无用。
key列
决定采用的索引。
key_len列
采用索引的可能最大长度。
ref列
在索引查找值时使用的列或常量。
rows列
估算大概要读取的行数。
filtered列
explain extended select xxx
时有的列。
符合条件行数的悲观估计。
Extra列
包括的值:
1 | using index: 使用覆盖索引; |
可以用Percona Toolkit
的pt-visual-explain
获得树形执行计划。
高性能mysql附录E-笔记-锁的调试
锁的类型:
- 表锁;
- 全局锁:
flush tables with read lock
或设置read_only=1
- 命名锁:表锁的一种,重命名或者删除表时创建;
- 字符锁:可以用
get_lock
等函数在服务器级别锁住/释放单个字符。
表锁
显式
1 | lock tables film read; |
隐式
1 | select sleep(30) from film limit 1 |
可以用mysqladmin debug
命令检测锁的持有信息。(输出的末尾)
全局读锁
show processlist
中status
是waiting for release of readlock
时,就是等待全局读锁了。
命名锁
show processlist
中status
是waiting for table
时,就是等待命名锁了。
还可以在show open tables
中看到命名锁的影响。
用户锁
1 | -- 试图获得名为`my_lock`的锁,超时时间100秒。 |
使用information_schema查看锁
https://dev.mysql.com/doc/refman/5.6/en/innodb-information-schema-examples.html
哪个事务在等待锁,哪个事务持有锁:
1 | SELECT |
查看阻塞查询的线程元凶:
1 | SELECT |
结果看线程4空闲了98秒,至少有一个线程等了它12秒,有1个线程在等待它。