慢查询排查以及优化
排查方式
SHOW PROCESSLIST
SHOW PROCESSLIST 只能查看到当前用户正在运行的线程,如果你是ROOT用户,那么是可以看到所有用户正在运行的线程
如果想看到其他用户的线程,则必须为此用户赋予 PROCESS 权限。
危害:
- 造成机器的 CPU 以及 IO 过高,影响到数据库实例。
- 阻塞 DDL 查询语句,会造成其他正常业务出现耗时过高。
- 会导致 mysql 出现 MDL 锁,影响到该机器上正常 SQL 的执行。
SHOW PROCESSLIST 只能查看到当前用户正在运行的线程,如果你是ROOT用户,那么是可以看到所有用户正在运行的线程
如果想看到其他用户的线程,则必须为此用户赋予 PROCESS 权限。
在进行旧的项目 review 的时候,我发现绝大多数的统计SQL都是基于 count(1)
来进行的,只有一少部分是基于 count(*)
,那么这两种写法到底有什么区别。
mysql中,常用的存储引擎有myisam
和innodb
,但是由于myisam
只支持表级别锁,而且还不支持事物,所以在mysql的5.5版本之后就将默认的存储引擎调整为innodb
。
以下实验基于 Mysql8.0.1
来进行
首先这里准备了一个表.
首先问两个问题:
本次的源代码以及测试的 Mysql 版本均为 8.0.17
在InnoDB里面,是通过快照读来实现RC
和PR
隔离级别的区分,因为在RC
隔离级别下,每一次的select都是一个快照读,所以是可以读取到已经提交的数据,从而导致幻读。所以在RC
隔离级别下,快照读和当前读都是可以出现幻读。
但是在PR
的隔离级别下,由于快照读仅仅只生成一次,所以在PR
级别下的快照读是无法出现幻读的,但是当前读确实可以出现幻读。
查看Mysql官方对于幻读
的定义。
The so-called phantom problem occurs within a transaction when the same query produces different sets of rows at different times.
幻读表示的是在一个事物里面 同一个select
语句,前后两次查询出来的结果是不相同的,需要注意的一点是,在InnoDB里面,幻读跟事物的隔离级别有关,更加准确的说是跟一个事物的快照和当前读有关
下面是在Mysql8.0.11版本下进行幻读的复现:
在临近上线之前,我们系统做了一次压力测试,发现有一个接口在高并发情况下会出现一个死锁的情况。。首先申明…不是我写的,我只是帮忙排查下。
随着对Mysql锁的深入了解,于是就准备写几篇文章来记录下Mysql各种事物和索引的情况下出现死锁的情况。
今天就介绍下在并发插入的情况下,哪几种情况会出现死锁:
在介绍锁的时候只会介绍跟本节相关的锁,而且只会讲述大概是什么,至于锁的更加详细的讲解可能会到以后再详细介绍。
在上一篇文章中,我们有一个表,里面的内容如下:
1 | mysql> select * from org_copy; |
这应该是一个很基本的一个mysql表,同时我们在上一篇文章中,也执行了如下SQL。
1 | mysql> explain SELECT * FROM org_copy WHERE org_name>'一级部门' and org_parent_id=1; |
本次的实验是基于Mysql8
版本。首先在数据库中有一个表,其结构如下:
1 | mysql> show create table org; |
可以看到在这个表中,有一个主键org_id
以及一个联合索引index_name
。其他的并无特别之处。
在Mysql里面,有一个最左原则,官网的介绍如下:
注意,此文章使用的Mysql变量均是用户变量
首先看一个需求,有如下数据表:
1 | mysql> select * from t1 order by area_id; |
可以看到,这是一个很非常普通的数据表。
假设有一个如下的业务场景如下:
需要记录一个商品或者股票的实时价格,每一个小时记录一次,而商品或者股票的数量十分多,这时业务发展到一定的程度之后就需要考虑数据库的设计。首先商品每个小时的价格肯定是需要入库的。其次每小时的购买人群以及各种埋点数据随之一起也要入库。以便于日后的数据分析。
随着数据量的增大,一般的解决方案是设置索引,然后再考虑是进行垂直还是水平分库分表。
但是一旦使用水平分库分表就会无形之间增加开发的复杂程度,而且分库分表之后考虑的各种因素也会随之而来增加数倍。例如各种表的唯一ID
以及如何进行维度的划分。