一、内存优化
# echo 0 >/proc/sys/vm/swappiness //临时
# vim /etc/sysctl.conf //永久
vm.swappiness=0
# sysctl -p
二、参数优化
参数 | 解释 | 用法 |
---|---|---|
Max_connections | Mysql的最大连接数,如果服务器的并发请求量比较大,可以调高这个值 | Max_connections=1024 |
back_log | mysql能暂存的连接数量,只有如果期望在一个短时间内有很多连接的时候需要增加它 | back_log=1024 |
wait_timeout | 指的是mysql在关闭一个非交互的连接之前所要等待的秒数 | wait_timeout=60 |
interactive_timeout | 指的是mysql在关闭一个交互的连接之前所需要等待的秒数 | interactive_timeout=1200 |
key_buffer_size | 指定索引缓冲区的大小,它决定索引处理的速度,尤其是索引读的速度 | key_buffer_size=64M |
query_cache_size | 查询缓存简称QC,使用查询缓冲,mysql将查询结果存放在缓冲区中,今后对于同样的select语句(区分大小写),将直接从缓冲区中读取结果。 | query_cache_size=128M |
query_cache_type | 缓存类型,决定缓存什么样的查询,设置为0,相当于禁用,设置为1,将会缓存所有的结果,设置为2,则只缓存在select语句中通过SQL_CACHE指定需要缓存的查询 | query_cache_type=1 |
max_connect_errors | 负责阻止过多尝试失败的客户端以防止暴力破解密码等情况,当超过指定次数,mysql服务器将禁止host的连接请求,直到mysql服务器重启或通过flush hosts命令清空此host的相关信息 | max_connect_errors=2000 |
sort_buffer_size | 每个需要进行排序的线程分配该大小的一个缓冲区 | sort_buffer_size=1M |
max_allowed_packet | mysql根据配置文件会限制,server接受的数据包大小 | max_allowed_packet=32M |
join_buffer_size | 用于表间关联缓存的大小,和sort_buffer_size一样,该参数对应的分配内存也是每个连接独享 | join_buffer_size=2M |
thread_cache_size | 服务器线程缓存,这个值表示可以重新利用保存在缓存中线程的数量,当断开连接时,那么客户端的线程将被放到缓存中以响应下一个客户而不是销毁(前提是缓存数未达上限),如果线程重新被请求,那么请求将从缓存中读取,如果缓存中是空的或者是新的请求,那么这个线程将被重新创建,如果有很多新的线程,增加这个值可以改善系统性能 | thread_cache_size=32 |
innodb_buffer_pool_size | InnoDB使用该参数指定大小的内存来缓冲数据和索引。对于单独的MySQL数据库服务器,最大可以把该值设置成物理内存的80%,一般我们建议不要超过物理内存的70% | innodb_buffer_pool_size=2048M |
innodb_flush_log_at_trx_commit | 控制了innodb将log buffer中的数据写入日志文件并flush磁盘的时间点,取值分别为0、1、2。0,表示当事务提交时,不做日志写入操作,而是每秒钟将log buffer中的数据写入日志文件并flush磁盘一次;1,每次事务的提交都会引起redo日志文件写入、flush磁盘的操作,确保了事务的ACID;2,每次事务提交引起写入日志文件的动作,但每秒钟完成一次flush磁盘操作。 | innodb_flush_log_at_trx_commit=1 |
innodb_thread_concurrency | 设置innodb线程的并发数量,默认值为0表示不限制 | innodb_thread_concurrency=8 |
innodb_log_buffer_size | 确定日志文件所用的内存大小,以M为单位。缓冲区更大能提高性能,对于较大的事务,可以增大缓存大小。 | innodb_log_buffer_size=128M |
innodb_log_file_size | 确定数据日志文件的大小,以M为单位,更大的设置可以提高性能 | innodb_log_file_size = 100M |
innodb_log_files_in_group | 以循环方式将日志文件写到多个文件 | nnodb_log_files_in_group = 3 |
read_buffer_size | MySql读入缓冲区大小 | read_buffer_size = 1M |
read_rnd_buffer_size | MySql的随机读(查询操作)缓冲区大小。当按任意顺序读取行时将分配一个随机读缓存区 | read_rnd_buffer_size = 1M |
bulk_insert_buffer_size | 批量插入数据缓存大小,可以有效提高插入效率,默认为8M | bulk_insert_buffer_size = 8M |
binary log | 什么时候刷新binlog到磁盘,每次事务commit | sync_binlog=1 |
max_connections=1024
back_log=128
wait_timeout=60
interactive_timeout=7200
key_buffer_size=16M
query_cache_size=64M
query_cache_type=1
query_cache_limit=50M
max_connect_errors=20
sort_buffer_size=2M
max_allowed_packet=32M
join_buffer_size=2M
thread_cache_size=200
innodb_buffer_pool_size=1024M
innodb_flush_log_at_trx_commit=1
innodb_log_buffer_size=32M
innodb_log_file_size=128M
innodb_log_files_in_group=3
binlog_cache_size=2M
max_binlog_cache_size=8M
max_binlog_size=512M
expire_logs_days=7
read_buffer_size=2M
read_rnd_buffer_size=2M
bulk_insert_buffer_size=8M
三、锁等待
1、查看锁等待
mysql01 [(none)]>SHOW STATUS LIKE 'innodb_row_lock%';
2、查看事务阻塞情况
mysql01 [(none)]>USE information_schema;
mysql01 [(none)]>SELECT * FROM information_schema.INNODB_TRX WHERE trx_state='LOCK WAIT';
参数 | 说明 |
---|---|
trx_id | 事务ID号 |
trx_state | 当前事务的状态 |
trx_mysql_thread_id | 连接层的,连接线程ID(SHOW PROCESSLIST ===>Id或trx_id ) |
trx_query | 当前被阻塞的操作 |
3、查看锁源
mysql01 [(none)]>SELECT * FROM sys.innodb_lock_waits;
参数 | 说明 |
---|---|
locked_table | 哪张表出现的等待 |
waiting_trx_id | 等待的事务(与上个视图trx_id 对应) |
waiting_pid | 等待的线程号(与上个视图trx_mysql_thread_id) |
blocking_trx_id | 锁源的事务ID |
blocking_pid | 锁源的线程号 |
查看锁源的thread_id
mysql01 [(none)]>SELECT * FROM performance_schema.threads WHERE processlist_id=15;
查看锁源的SQL语句
mysql01 [(none)]>SELECT * FROM performance_schema.`events_statements_current` WHERE thread_id=41; //当前在执行的语句
mysql01 [(none)]>SELECT * FROM performance_schema.`events_statements_history` WHERE thread_id=41; //执行语句的历史
四、死锁监控
死锁写入错误日志
# vim /etc/my.cnf
innodb_print_all_deadlocks = 1
mysql01 [(none)]>show engine innodb status\G
mysql01 [(none)]>show variables like '%deadlock%';
查看 MySQL 数据库中死锁的相关信息,可以执行 show engine innodb status\G
来进行查看,重点关注 “LATEST DETECTED DEADLOCK” 部分。
避免线上业务因死锁造成的不必要的影响的开发建议
-
更新 SQL 的 where 条件时尽量用索引;
-
加锁索引准确,缩小锁定范围;
-
减少范围更新,尤其非主键/非唯一索引上的范围更新。
-
控制事务大小,减少锁定数据量和锁定时间长度 (innodb_row_lock_time_avg)。
-
加锁顺序一致,尽可能一次性锁定所有所需的数据行。
五、锁表锁库操作
如果对mysql进行操作时,网络中断或SQL异常 , 可能会导致表或者库卡死 , 锁死,无法进行后续操作 (如果用 navicat 等工具连接操作, 操作都会在转圈圈,无法完成操作)。此时要找出造成锁库锁表的SQL语句的进程,将其杀死,中断其操作执行,即可解决锁库锁表。
1、查看锁死SQL的进程ID
# 进程ID在trx_mysql_thread_id那一列
select id, db, user, host, command, time, state, info
from information_schema.processlist
where command != 'Sleep'
order by time desc
或者
SELECT
concat( 'kill ', id, ';' )
FROM
information_schema.PROCESSLIST
WHERE
Command = 'Sleep'
AND Time > 10
AND db = 'test'
ORDER BY
Time DESC;
# sql语句在info列,进程ID在ID列
show processlist;
2、杀死相关进程
kill -9 进程号
六、主从优化
gtid_mode=ON
enforce_gtid_consistency=ON
log_slave_updates=ON
slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=16 //cpu核心数作为标准(50%)
master_info_repository=TABLE
relay_log_info_repository=TABLE
relay_log_recovery=ON
七、性能查询工具
show profile
# 此工具默认是禁用的,可以通过服务器变量进行修改,当设置完成之后,在服务器上执行的所有语句,都会测量其耗费的时间和其他一些查询执行状态变更相关的数据。在mysq的命令行模式下只能显示两位小数的时间,可以使用如下命令查看具体的执行时间
set profiling=1; # 开启 profiling 参数(5.*版本可用)
show profiles; # 执行该命令可以查看详细的每个步骤的时间
show profile; # 显示最近语句执行的详细资源占用信息
show profile for query 2; # 根据 show profiles 列表中的 Query_ID ,选择显示某条记录的性能分析信息
SHOW PROFILE
and SHOW PROFILES
语句已弃用 ;期望它们在未来的 MySQL 版本中被删除。改用Performance Schema;
type | 说明 | 语句 |
---|---|---|
all | 显示所有性能信息 | show profile all for query n |
block io | 显示块io操作的次数 | show profile block io for query n |
context switches | 显示上下文切换次数,被动和主动 | show profile context switches for query n |
cpu | 显示用户cpu时间、系统cpu时间 | show profile cpu for query n |
IPC | 显示发送和接受的消息数量 | show profile ipc for query n |
Memory | 暂未实现 | |
page faults | 显示页错误数量 | show profile page faults for query n |
source | 显示源码中的函数名称与位置 | show profile source for query n |
swaps | 显示swap的次数 | show profile swaps for query n |
八、performance_schema的介绍
MySQL的performance schema 用于监控MySQL server在一个较低级别的运行过程中的资源消耗、资源等待等情况。
特点如下:
1、提供了一种在数据库运行时实时检查server的内部执行情况的方法。performance_schema 数据库中的表使用performance_schema存储引擎。该数据库主要关注数据库运行过程中的性能相关的数据,与information_schema不同,information_schema主要关注server运行过程中的元数据信息
2、performance_schema通过监视server的事件来实现监视server内部运行情况, “事件”就是server内部活动中所做的任何事情以及对应的时间消耗,利用这些信息来判断server中的相关资源消耗在了哪里?一般来说,事件可以是函数调用、操作系统的等待、SQL语句执行的阶段(如sql语句执行过程中的parsing 或 sorting阶段)或者整个SQL语句与SQL语句集合。事件的采集可以方便的提供server中的相关存储引擎对磁盘文件、表I/O、表锁等资源的同步调用信息。
3、performance_schema中的事件与写入二进制日志中的事件(描述数据修改的events)、事件计划调度程序(这是一种存储程序)的事件不同。performance_schema中的事件记录的是server执行某些活动对某些资源的消耗、耗时、这些活动执行的次数等情况。
4、performance_schema中的事件只记录在本地server的performance_schema中,其下的这些表中数据发生变化时不会被写入binlog中,也不会通过复制机制被复制到其他server中。
5、 当前活跃事件、历史事件和事件摘要相关的表中记录的信息。能提供某个事件的执行次数、使用时长。进而可用于分析某个特定线程、特定对象(如mutex或file)相关联的活动。
6、PERFORMANCE_SCHEMA存储引擎使用server源代码中的“检测点”来实现事件数据的收集。对于performance_schema实现机制本身的代码没有相关的单独线程来检测,这与其他功能(如复制或事件计划程序)不同
7、收集的事件数据存储在performance_schema数据库的表中。这些表可以使用SELECT语句查询,也可以使用SQL语句更新performance_schema数据库中的表记录(如动态修改performance_schema的setup_*开头的几个配置表,但要注意:配置表的更改会立即生效,这会影响数据收集)
8、performance_schema的表中的数据不会持久化存储在磁盘中,而是保存在内存中,一旦服务器重启,这些数据会丢失(包括配置表在内的整个performance_schema下的所有数据)
9、MySQL支持的所有平台中事件监控功能都可用,但不同平台中用于统计事件时间开销的计时器类型可能会有所差异。
1、performance schema入门
在mysql的5.7版本中,性能模式是默认开启的,如果想要显式的关闭的话需要修改配置文件,不能直接进行修改,会报错Variable 'performance_schema' is a read only variable。
--查看performance_schema的属性
mysql> SHOW VARIABLES LIKE 'performance_schema';
+--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| performance_schema | ON |
+--------------------+-------+
1 row in set (0.01 sec)
--在配置文件中修改performance_schema的属性值,on表示开启,off表示关闭
[mysqld]
performance_schema=ON
--切换数据库
use performance_schema;
--查看当前数据库下的所有表,会看到有很多表存储着相关的信息
show tables;
--可以通过show create table tablename来查看创建表的时候的表结构
mysql> show create table setup_consumers;
+-----------------+---------------------------------
| Table | Create Table
+-----------------+---------------------------------
| setup_consumers | CREATE TABLE `setup_consumers` (
`NAME` varchar(64) NOT NULL,
`ENABLED` enum('YES','NO') NOT NULL
) ENGINE=PERFORMANCE_SCHEMA DEFAULT CHARSET=utf8 |
+-----------------+---------------------------------
1 row in set (0.00 sec)
想要搞明白后续的内容,需要理解两个基本概念:
instruments: 生产者,用于采集mysql中各种各样的操作产生的事件信息,对应配置表中的配置项我们可以称为监控采集配置项。
consumers:消费者,对应的消费者表用于存储来自instruments采集的数据,对应配置表中的配置项我们可以称为消费存储配置项。
2、performance_schema表的分类
performance_schema库下的表可以按照监视不同的纬度就行分组。
--语句事件记录表,这些表记录了语句事件信息,当前语句事件表events_statements_current、历史语句事件表events_statements_history和长语句历史事件表events_statements_history_long、以及聚合后的摘要表summary,其中,summary表还可以根据帐号(account),主机(host),程序(program),线程(thread),用户(user)和全局(global)再进行细分)
show tables like '%statement%';
--等待事件记录表,与语句事件类型的相关记录表类似:
show tables like '%wait%';
--阶段事件记录表,记录语句执行的阶段事件的表
show tables like '%stage%';
--事务事件记录表,记录事务相关的事件的表
show tables like '%transaction%';
--监控文件系统层调用的表
show tables like '%file%';
--监视内存使用的表
show tables like '%memory%';
--动态对performance_schema进行配置的配置表
show tables like '%setup%';
3、performance_schema的简单配置与使用
数据库刚刚初始化并启动时,并非所有instruments(事件采集项,在采集项的配置表中每一项都有一个开关字段,或为YES,或为NO)和consumers(与采集项类似,也有一个对应的事件类型保存表配置项,为YES就表示对应的表保存性能数据,为NO就表示对应的表不保存性能数据)都启用了,所以默认不会收集所有的事件,可能你需要检测的事件并没有打开,需要进行设置,可以使用如下两个语句打开对应的instruments和consumers(行计数可能会因MySQL版本而异)。
--打开等待事件的采集器配置项开关,需要修改setup_instruments配置表中对应的采集器配置项
UPDATE setup_instruments SET ENABLED = 'YES', TIMED = 'YES'where name like 'wait%';
--打开等待事件的保存表配置开关,修改setup_consumers配置表中对应的配置项
UPDATE setup_consumers SET ENABLED = 'YES'where name like '%wait%';
--当配置完成之后可以查看当前server正在做什么,可以通过查询events_waits_current表来得知,该表中每个线程只包含一行数据,用于显示每个线程的最新监视事件
select * from events_waits_current\G
*************************** 1. row ***************************
THREAD_ID: 11
EVENT_ID: 570
END_EVENT_ID: 570
EVENT_NAME: wait/synch/mutex/innodb/buf_dblwr_mutex
SOURCE:
TIMER_START: 4508505105239280
TIMER_END: 4508505105270160
TIMER_WAIT: 30880
SPINS: NULL
OBJECT_SCHEMA: NULL
OBJECT_NAME: NULL
INDEX_NAME: NULL
OBJECT_TYPE: NULL
OBJECT_INSTANCE_BEGIN: 67918392
NESTING_EVENT_ID: NULL
NESTING_EVENT_TYPE: NULL
OPERATION: lock
NUMBER_OF_BYTES: NULL
FLAGS: NULL
/*该信息表示线程id为11的线程正在等待buf_dblwr_mutex锁,等待事件为30880
属性说明:
id:事件来自哪个线程,事件编号是多少
event_name:表示检测到的具体的内容
source:表示这个检测代码在哪个源文件中以及行号
timer_start:表示该事件的开始时间
timer_end:表示该事件的结束时间
timer_wait:表示该事件总的花费时间
注意:_current表中每个线程只保留一条记录,一旦线程完成工作,该表中不会再记录该线程的事件信息
*/
/*
_history表中记录每个线程应该执行完成的事件信息,但每个线程的事件信息只会记录10条,再多就会被覆盖,*_history_long表中记录所有线程的事件信息,但总记录数量是10000,超过就会被覆盖掉
*/
select thread_id,event_id,event_name,timer_wait from events_waits_history order by thread_id limit 21;
/*
summary表提供所有事件的汇总信息,该组中的表以不同的方式汇总事件数据(如:按用户,按主机,按线程等等)。例如:要查看哪些instruments占用最多的时间,可以通过对events_waits_summary_global_by_event_name表的COUNT_STAR或SUM_TIMER_WAIT列进行查询(这两列是对事件的记录数执行COUNT(*)、事件记录的TIMER_WAIT列执行SUM(TIMER_WAIT)统计而来)
*/
SELECT EVENT_NAME,COUNT_STAR FROM events_waits_summary_global_by_event_name ORDER BY COUNT_STAR DESC LIMIT 10;
/*
instance表记录了哪些类型的对象会被检测。这些对象在被server使用时,在该表中将会产生一条事件记录,例如,file_instances表列出了文件I/O操作及其关联文件名
*/
select * from file_instances limit 20;
4、常用配置项的参数说明
1、启动选项
performance_schema_consumer_events_statements_current=TRUE
是否在mysql server启动时就开启events_statements_current表的记录功能(该表记录当前的语句事件信息),启动之后也可以在setup_consumers表中使用UPDATE语句进行动态更新setup_consumers配置表中的events_statements_current配置项,默认值为TRUE
performance_schema_consumer_events_statements_history=TRUE
与performance_schema_consumer_events_statements_current选项类似,但该选项是用于配置是否记录语句事件短历史信息,默认为TRUE
performance_schema_consumer_events_stages_history_long=FALSE
与performance_schema_consumer_events_statements_current选项类似,但该选项是用于配置是否记录语句事件长历史信息,默认为FALSE
除了statement(语句)事件之外,还支持:wait(等待)事件、state(阶段)事件、transaction(事务)事件,他们与statement事件一样都有三个启动项分别进行配置,但这些等待事件默认未启用,如果需要在MySQL Server启动时一同启动,则通常需要写进my.cnf配置文件中
performance_schema_consumer_global_instrumentation=TRUE
是否在MySQL Server启动时就开启全局表(如:mutex_instances、rwlock_instances、cond_instances、file_instances、users、hostsaccounts、socket_summary_by_event_name、file_summary_by_instance等大部分的全局对象计数统计和事件汇总统计信息表 )的记录功能,启动之后也可以在setup_consumers表中使用UPDATE语句进行动态更新全局配置项
默认值为TRUE
performance_schema_consumer_statements_digest=TRUE
是否在MySQL Server启动时就开启events_statements_summary_by_digest 表的记录功能,启动之后也可以在setup_consumers表中使用UPDATE语句进行动态更新digest配置项
默认值为TRUE
performance_schema_consumer_thread_instrumentation=TRUE
是否在MySQL Server启动时就开启
events_xxx_summary_by_yyy_by_event_name表的记录功能,启动之后也可以在setup_consumers表中使用UPDATE语句进行动态更新线程配置项
默认值为TRUE
performance_schema_instrument[=name]
是否在MySQL Server启动时就启用某些采集器,由于instruments配置项多达数千个,所以该配置项支持key-value模式,还支持%号进行通配等,如下:
# [=name]可以指定为具体的Instruments名称(但是这样如果有多个需要指定的时候,就需要使用该选项多次),也可以使用通配符,可以指定instruments相同的前缀+通配符,也可以使用%代表所有的instruments
## 指定开启单个instruments
--performance-schema-instrument= 'instrument_name=value'
## 使用通配符指定开启多个instruments
--performance-schema-instrument= 'wait/synch/cond/%=COUNTED'
## 开关所有的instruments
--performance-schema-instrument= '%=ON'
--performance-schema-instrument= '%=OFF'
注意,这些启动选项要生效的前提是,需要设置performance_schema=ON。另外,这些启动选项虽然无法使用show variables语句查看,但我们可以通过setup_instruments和setup_consumers表查询这些选项指定的值。
2、系统变量
show variables like '%performance_schema%';
--重要的属性解释
performance_schema=ON
/*
控制performance_schema功能的开关,要使用MySQL的performance_schema,需要在mysqld启动时启用,以启用事件收集功能
该参数在5.7.x之前支持performance_schema的版本中默认关闭,5.7.x版本开始默认开启
注意:如果mysqld在初始化performance_schema时发现无法分配任何相关的内部缓冲区,则performance_schema将自动禁用,并将performance_schema设置为OFF
*/
performance_schema_digests_size=10000
/*
控制events_statements_summary_by_digest表中的最大行数。如果产生的语句摘要信息超过此最大值,便无法继续存入该表,此时performance_schema会增加状态变量
*/
performance_schema_events_statements_history_long_size=10000
/*
控制events_statements_history_long表中的最大行数,该参数控制所有会话在events_statements_history_long表中能够存放的总事件记录数,超过这个限制之后,最早的记录将被覆盖
全局变量,只读变量,整型值,5.6.3版本引入 * 5.6.x版本中,5.6.5及其之前的版本默认为10000,5.6.6及其之后的版本默认值为-1,通常情况下,自动计算的值都是10000 * 5.7.x版本中,默认值为-1,通常情况下,自动计算的值都是10000
*/
performance_schema_events_statements_history_size=10
/*
控制events_statements_history表中单个线程(会话)的最大行数,该参数控制单个会话在events_statements_history表中能够存放的事件记录数,超过这个限制之后,单个会话最早的记录将被覆盖
全局变量,只读变量,整型值,5.6.3版本引入 * 5.6.x版本中,5.6.5及其之前的版本默认为10,5.6.6及其之后的版本默认值为-1,通常情况下,自动计算的值都是10 * 5.7.x版本中,默认值为-1,通常情况下,自动计算的值都是10
除了statement(语句)事件之外,wait(等待)事件、state(阶段)事件、transaction(事务)事件,他们与statement事件一样都有三个参数分别进行存储限制配置,有兴趣的同学自行研究,这里不再赘述
*/
performance_schema_max_digest_length=1024
/*
用于控制标准化形式的SQL语句文本在存入performance_schema时的限制长度,该变量与max_digest_length变量相关(max_digest_length变量含义请自行查阅相关资料)
全局变量,只读变量,默认值1024字节,整型值,取值范围0~1048576
*/
performance_schema_max_sql_text_length=1024
/*
控制存入events_statements_current,events_statements_history和events_statements_history_long语句事件表中的SQL_TEXT列的最大SQL长度字节数。 超出系统变量performance_schema_max_sql_text_length的部分将被丢弃,不会记录,一般情况下不需要调整该参数,除非被截断的部分与其他SQL比起来有很大差异
全局变量,只读变量,整型值,默认值为1024字节,取值范围为0~1048576,5.7.6版本引入
降低系统变量performance_schema_max_sql_text_length值可以减少内存使用,但如果汇总的SQL中,被截断部分有较大差异,会导致没有办法再对这些有较大差异的SQL进行区分。 增加该系统变量值会增加内存使用,但对于汇总SQL来讲可以更精准地区分不同的部分。
*/
5、重要配置表的相关说明
配置表之间存在相互关联关系,按照配置影响的先后顺序,可添加为
/*
performance_timers表中记录了server中有哪些可用的事件计时器
字段解释:
timer_name:表示可用计时器名称,CYCLE是基于CPU周期计数器的定时器
timer_frequency:表示每秒钟对应的计时器单位的数量,CYCLE计时器的换算值与CPU的频率相关、
timer_resolution:计时器精度值,表示在每个计时器被调用时额外增加的值
timer_overhead:表示在使用定时器获取事件时开销的最小周期值
*/
select * from performance_timers;
/*
setup_timers表中记录当前使用的事件计时器信息
字段解释:
name:计时器类型,对应某个事件类别
timer_name:计时器类型名称
*/
select * from setup_timers;
/*
setup_consumers表中列出了consumers可配置列表项
字段解释:
NAME:consumers配置名称
ENABLED:consumers是否启用,有效值为YES或NO,此列可以使用UPDATE语句修改。
*/
select * from setup_consumers;
/*
setup_instruments 表列出了instruments 列表配置项,即代表了哪些事件支持被收集:
字段解释:
NAME:instruments名称,instruments名称可能具有多个部分并形成层次结构
ENABLED:instrumetns是否启用,有效值为YES或NO,此列可以使用UPDATE语句修改。如果设置为NO,则这个instruments不会被执行,不会产生任何的事件信息
TIMED:instruments是否收集时间信息,有效值为YES或NO,此列可以使用UPDATE语句修改,如果设置为NO,则这个instruments不会收集时间信息
*/
SELECT * FROM setup_instruments;
/*
setup_actors表的初始内容是匹配任何用户和主机,因此对于所有前台线程,默认情况下启用监视和历史事件收集功能
字段解释:
HOST:与grant语句类似的主机名,一个具体的字符串名字,或使用“%”表示“任何主机”
USER:一个具体的字符串名称,或使用“%”表示“任何用户”
ROLE:当前未使用,MySQL 8.0中才启用角色功能
ENABLED:是否启用与HOST,USER,ROLE匹配的前台线程的监控功能,有效值为:YES或NO
HISTORY:是否启用与HOST, USER,ROLE匹配的前台线程的历史事件记录功能,有效值为:YES或NO
*/
SELECT * FROM setup_actors;
/*
setup_objects表控制performance_schema是否监视特定对象。默认情况下,此表的最大行数为100行。
字段解释:
OBJECT_TYPE:instruments类型,有效值为:“EVENT”(事件调度器事件)、“FUNCTION”(存储函数)、“PROCEDURE”(存储过程)、“TABLE”(基表)、“TRIGGER”(触发器),TABLE对象类型的配置会影响表I/O事件(wait/io/table/sql/handler instrument)和表锁事件(wait/lock/table/sql/handler instrument)的收集
OBJECT_SCHEMA:某个监视类型对象涵盖的数据库名称,一个字符串名称,或“%”(表示“任何数据库”)
OBJECT_NAME:某个监视类型对象涵盖的表名,一个字符串名称,或“%”(表示“任何数据库内的对象”)
ENABLED:是否开启对某个类型对象的监视功能,有效值为:YES或NO。此列可以修改
TIMED:是否开启对某个类型对象的时间收集功能,有效值为:YES或NO,此列可以修改
*/
SELECT * FROM setup_objects;
/*
threads表对于每个server线程生成一行包含线程相关的信息,
字段解释:
THREAD_ID:线程的唯一标识符(ID)
NAME:与server中的线程检测代码相关联的名称(注意,这里不是instruments名称)
TYPE:线程类型,有效值为:FOREGROUND、BACKGROUND。分别表示前台线程和后台线程
PROCESSLIST_ID:对应INFORMATION_SCHEMA.PROCESSLIST表中的ID列。
PROCESSLIST_USER:与前台线程相关联的用户名,对于后台线程为NULL。
PROCESSLIST_HOST:与前台线程关联的客户端的主机名,对于后台线程为NULL。
PROCESSLIST_DB:线程的默认数据库,如果没有,则为NULL。
PROCESSLIST_COMMAND:对于前台线程,该值代表着当前客户端正在执行的command类型,如果是sleep则表示当前会话处于空闲状态
PROCESSLIST_TIME:当前线程已处于当前线程状态的持续时间(秒)
PROCESSLIST_STATE:表示线程正在做什么事情。
PROCESSLIST_INFO:线程正在执行的语句,如果没有执行任何语句,则为NULL。
PARENT_THREAD_ID:如果这个线程是一个子线程(由另一个线程生成),那么该字段显示其父线程ID
ROLE:暂未使用
INSTRUMENTED:线程执行的事件是否被检测。有效值:YES、NO
HISTORY:是否记录线程的历史事件。有效值:YES、NO *
THREAD_OS_ID:由操作系统层定义的线程或任务标识符(ID):
*/
select * from threads
注意:在performance_schema库中还包含了很多其他的库和表,能对数据库的性能做完整的监控,大家需要参考官网详细了解。
6、performance_schema实践操作
基本了解了表的相关信息之后,可以通过这些表进行实际的查询操作来进行实际的分析。
--1、哪类的SQL执行最多?
SELECT DIGEST_TEXT,COUNT_STAR,FIRST_SEEN,LAST_SEEN FROM events_statements_summary_by_digest ORDER BY COUNT_STAR DESC
--2、哪类SQL的平均响应时间最多?
SELECT DIGEST_TEXT,AVG_TIMER_WAIT FROM events_statements_summary_by_digest ORDER BY COUNT_STAR DESC
--3、哪类SQL排序记录数最多?
SELECT DIGEST_TEXT,SUM_SORT_ROWS FROM events_statements_summary_by_digest ORDER BY COUNT_STAR DESC
--4、哪类SQL扫描记录数最多?
SELECT DIGEST_TEXT,SUM_ROWS_EXAMINED FROM events_statements_summary_by_digest ORDER BY COUNT_STAR DESC
--5、哪类SQL使用临时表最多?
SELECT DIGEST_TEXT,SUM_CREATED_TMP_TABLES,SUM_CREATED_TMP_DISK_TABLES FROM events_statements_summary_by_digest ORDER BY COUNT_STAR DESC
--6、哪类SQL返回结果集最多?
SELECT DIGEST_TEXT,SUM_ROWS_SENT FROM events_statements_summary_by_digest ORDER BY COUNT_STAR DESC
--7、哪个表物理IO最多?
SELECT file_name,event_name,SUM_NUMBER_OF_BYTES_READ,SUM_NUMBER_OF_BYTES_WRITE FROM file_summary_by_instance ORDER BY SUM_NUMBER_OF_BYTES_READ + SUM_NUMBER_OF_BYTES_WRITE DESC
--8、哪个表逻辑IO最多?
SELECT object_name,COUNT_READ,COUNT_WRITE,COUNT_FETCH,SUM_TIMER_WAIT FROM table_io_waits_summary_by_table ORDER BY sum_timer_wait DESC
--9、哪个索引访问最多?
SELECT OBJECT_NAME,INDEX_NAME,COUNT_FETCH,COUNT_INSERT,COUNT_UPDATE,COUNT_DELETE FROM table_io_waits_summary_by_index_usage ORDER BY SUM_TIMER_WAIT DESC
--10、哪个索引从来没有用过?
SELECT OBJECT_SCHEMA,OBJECT_NAME,INDEX_NAME FROM table_io_waits_summary_by_index_usage WHERE INDEX_NAME IS NOT NULL AND COUNT_STAR = 0 AND OBJECT_SCHEMA <> 'mysql' ORDER BY OBJECT_SCHEMA,OBJECT_NAME;
--11、哪个等待事件消耗时间最多?
SELECT EVENT_NAME,COUNT_STAR,SUM_TIMER_WAIT,AVG_TIMER_WAIT FROM events_waits_summary_global_by_event_name WHERE event_name != 'idle' ORDER BY SUM_TIMER_WAIT DESC
--12-1、剖析某条SQL的执行情况,包括statement信息,stege信息,wait信息
SELECT EVENT_ID,sql_text FROM events_statements_history WHERE sql_text LIKE '%count(*)%';
--12-2、查看每个阶段的时间消耗
SELECT event_id,EVENT_NAME,SOURCE,TIMER_END - TIMER_START FROM events_stages_history_long WHERE NESTING_EVENT_ID = 1553;
--12-3、查看每个阶段的锁等待情况
SELECT event_id,event_name,source,timer_wait,object_name,index_name,operation,nesting_event_id FROM events_waits_history_longWHERE nesting_event_id = 1553;
九、show processlist
使用show processlist查看连接的线程个数,来观察是否有大量线程处于不正常的状态或者其他不正常的特征
属性 | 说明 |
---|---|
id | 表示session id |
user | 表示操作的用户 |
host | 表示操作的主机 |
db | 表示操作的数据库 |
command | 表示当前状态 |
info | 表示详细的sql语句 |
time | 表示相应命令执行时间 |
state | 表示命令执行状态 |
command状态
状态 | 说明 |
---|---|
sleep | 线程正在等待客户端发送新的请求 |
query | 线程正在执行查询或正在将结果发送给客户端 |
locked | 在mysql的服务层,该线程正在等待表锁 |
analyzing and statistics | 线程正在收集存储引擎的统计信息,并生成查询的执行计划 |
Copying to tmp table | 线程正在执行查询,并且将其结果集都复制到一个临时表中 |
sorting result | 线程正在对结果集进行排序 |
sending data | 线程可能在多个状态之间传送数据,或者在生成结果集或者向客户端返回数据 |
十、schema与数据类型优化
1、数据类型的优化
1、更小的通常更好
应该尽量使用可以正确存储数据的最小数据类型,更小的数据类型通常更快,因为它们占用更少的磁盘、内存和CPU缓存,并且处理时需要的CPU周期更少,但是要确保没有低估需要存储的值的范围,如果无法确认哪个数据类型,就选择你认为不会超过范围的最小类型
2、简单就好
简单数据类型的操作通常需要更少的CPU周期,例如
1、整型比字符操作代价更低,因为字符集和校对规则是字符比较比整型比较更复杂。
2、使用mysq自建类型而不是字符串来存储日期和时间
3、用整型存储IP地址
3、尽量避免null
如果查询中包含可为NULL的列,对mysql来说很难优化,因为可为null的列使的索引、索引统计和值比较都更加复杂,坦白来说,通常情况下null的列改为not null带来的性能提升比较小,所有没有必要将所有的表的schema进行修改,但是应该尽量避免设计成可为null的列
4、实际细则
1、整数类型
可以使用的几种整数类型:TINYINT,SMALLINT,MEDIUMINT,INT,BIGINT,分别使用8,16,24,32,64位存储空间。
尽量使用满足需求的最小数据类型
2、字符和字符串类型
1、varchar根据实际内容长度保存数据
1、使用最小的符合需求的长度。
2、varchar(n)n小于等于255使用额外一个字节保存长度,n>255使用额外两个字节保存长度。
3、varchar(5)与varchar(255)保存同样的内容,硬盘存储空间相同,但内存空间占用不同,是指定的大小。
4、varchar在mysql5.6之前变更长度,或者从255一下变更到255以上时时,都会导致锁表。
应用场景
1、存储长度波动较大的数据,如:文章,有的会很短有的会很长
2、字符串很少更新的场景,每次更新后都会重算并使用应用场景额外存储空间保存长度
3、适合保存多字节字符,如:汉字,特殊字符等
2、char固定长度的字符串
1、最大长度:255
2、会自动删除未尾的空格
3、检索效率、写效率会比varchar高,以空间换时间
应用场景
1、存储长度波动不大的数据,如:md5摘要
2、存储短字符串、经常更新的字符串
3、BLOB和TEXT类型
MySQL把每个BLOB和TEXT值当作一个独立的对象处理。两者都是为了存储很大数据而设计的字符串类型,分别采用二进制和字符方式存储。
4、datetime和timestamp
1、datetime
1、占用8个字节
2、与时区无关,数据库底层时区配置,对datetime无效
3、可保存到毫秒
4、可保存时间范围大
5、不要使用字符串存储日期类型,占用空间大,损失日期类型函数的便捷性
2、timestamp
1、占用4个字节
2、时间范围:1970-01-01到2038-01-19
3、精确到秒
4、采用整形存储
5、依赖数据库设置的时区
6、自动更新timestamp列的值
3、data
1、占用的字节数比使用字符串、datetime、int存储要少,使用date类型只需要3个字节
2、使用date类型还可以利用日期时间函数进行日期之间的计算
3、date类型用于保存1000-01-01到9999-12-31之间的日期
5、使用枚举代替字符串类型
有时可以使用枚举类型代替常用的字符串类型,mysql存储枚举类型会非常紧凑,会根据列表值的数期压缩到一个或两个字节中,mysql在内部会将每个值在列表中的位置保存为整数,并且在表的.frm文件中保存“数字·字符串“映射关系的查找表
6、特殊类型数据
人们经常使用varchar(15)来存储jp地址,然而,它的本质是32位无符号整数不是字符串,可以使用INET_ATON0和INET_NTOA函数在这两种表示方法之间转换。
2、合理使用范式和反范式
1、范式
优点
1、范式化的更新通常比反范式要快
2、当数据较好的范式化后,很少或者没有重复的数据
3、范式化的数据比较小,可以放在内存中,操作比较快
缺点
1、通常需要进行关联
2、反范式
优点
1、所有的数据都在同一张表中,可以避免关联
2、可以设计有效的索引;
缺点
1、表格内的冗余较多,删除数据时候会造成表有些有用的信息丢失
3、主键的选择
1、代理主键
与业务无关的,无意义的数字序列
2、自然主键
事物属性中的自然唯一标识
3、推荐使用代理主键
它们不与业务耦合,因此更容易维护
一个大多数表,最好是全部表,通用的键策略能够减少需要编写的源码数量,减少系统的总体拥有成本
4、字符集的选择
字符集直接决定了数据在MySQL中的存储编码方式,由于同样的内容使用不同字符集表示所占用的空间大小会有较大的差异,所以通过使用合适的字符集,可以帮助我们尽可能减少数据量,进而减少IO操作次数。
1、纯拉丁字符能表示的内容,没必要选择 latin1 之外的其他字符编码,因为这会节省大量的存储空间。
2、如果我们可以确定不需要存放多种语言,就没必要非得使用UTF8或者其他UNICODE字符类型,这回造成大量的存储空间浪费。
3、MySQL的数据类型可以精确到字段,所以当我们需要大型数据库中存放多字节数据的时候,可以通过对不同表不同字段使用不同的数据类型来较大程度减小数据存储量,进而降低 IO 操作次数并提高缓存命中率。
5、存储引擎的选择
存储引擎的对比
MyISAM | InnoDB | |
---|---|---|
索引类型 | 非聚簇索引 | 聚簇索引 |
支持事务 | 否 | 是 |
支持表锁 | 是 | 是 |
支持行锁 | 否 | 是 |
支持外键 | 否 | 是 |
支持全文索引 | 是 | 是(5.6后支持) |
适合操作类型 | 大量select | 大量insert、delete、update |
6、适当的数据冗余
1、被频繁引用且只能通过 Join 2张(或者更多)大表的方式才能得到的独立小字段。
2、这样的场景由于每次Join仅仅只是为了取得某个小字段的值,Join到的记录又大,会造成大量不必要的 IO,完全可以通过空间换取时间的方式来优化。不过,冗余的同时需要确保数据的一致性不会遭到破坏,确保更新的同时冗余字段也被更新。
7、适当拆分
当我们的表中存在类似于 TEXT 或者是很大的 VARCHAR类型的大字段的时候,如果我们大部分访问这张表的时候都不需要这个字段,我们就该义无反顾的将其拆分到另外的独立表中,以减少常用数据所占用的存储空间。这样做的一个明显好处就是每个数据块中可以存储的数据条数可以大大增加,既减少物理 IO 次数,也能大大提高内存中的缓存命中率。
评论区