爱收集资源网

如何使用explain分析索引,以及showprofiles分析SQL语句执行资源消耗的学习

网络整理 2022-04-20 00:59

前言

我们讲了索引是什么,如何使用explain来分析索引使用情况,如何优化索引,以及show profile来分析SQL语句执行的资源消耗。今天我们来聊聊MySQL的各种锁。这里我们使用 InnoDB 作为存储引擎。

准备

创建表 tb_innodb_lock

如果存在则删除表 test_innodb_lock;

创建表 test_innodb_lock (

一个 INT (11),

b VARCHAR (20)

) ENGINE INNODB 默认字符集 = utf8;

插入test_innodb_lock值(1,'a');

插入test_innodb_lock值(2,'b');

插入test_innodb_lock值(3,'c');

插入test_innodb_lock值(4,'d');

插入test_innodb_lock值(5,'e');

创建索引

在 test_innodb_lock(a) 上创建索引 idx_lock_a;

在 test_innodb_lock(b) 上创建索引 idx_lock_b;

MySQL的各种锁演示先把自动提交事务改为手动提交:set autocommit=0;

我们启动两个会话窗口 A 和 B,模拟一个获得锁,另一个被阻塞。

Row Lock (Write & Read) 一个窗口执行

更新 test_innodb_lock set b='a1' where a=1;

从 test_innodb_lock 中选择 *;

我们可以看到A窗口可以看到B窗口执行的更新结果

从 test_innodb_lock 中选择 *;

我们可以看到B窗口看不到更新的结果,但是还是看到了旧的数据。这是因为a=1的行被A窗口执行的SQL语句锁住了,commit没有执行。操作。所以窗口 B 仍然看到旧数据。这是 MySQL 隔离级别中的“已提交读”。窗口A执行提交操作

COMMIT;窗口 B 查询

从 test_innodb_lock 中选择 *;

此时我们发现窗口B已经读取了最新的数据

Row Lock (Write & Write) 窗口 A 执行记录 a = 1 的更新

更新 test_innodb_lock set b='a2' where a=1;

此时没有提交,锁由窗口A持有。窗口B也对a=1的记录进行更新

更新 test_innodb_lock set b='a3' where a=1;

可以看出窗口B一直处于阻塞状态,因为窗口A还没有执行commit,仍然持有锁。窗口 B 无法获取 a = 1 行的锁,因此它一直处于阻塞和等待状态。窗口A执行提交操作

提交;窗口 B 中的更改

此时可以看到窗口B已经执行成功

表锁

当索引失败时,行锁会升级为表锁。索引失效的方法之一是自动或手动更改索引。 a 字段本身是一个整数。当我们添加引号时,它就变成了一个字符串。此时,索引将无效。窗口 A 用 a = 1 更新记录

update test_innodb_lock set b='a4' where a=1 or a=2;window B 用 a = 2 更新记录

更新 test_innodb_lock set b='b1' where a=3;

这时候发现虽然A和B窗口更新的行不同,但是B窗口还是被阻塞了表行锁定的时候能查询么,因为A窗口的索引无效,导致行锁升级为表锁,加锁整张桌子。 ,索引窗口 B 被阻塞。窗口A执行提交操作

提交;窗口 B 中的更改

此时可以看到窗口B已经执行成功

什么是间隙锁

当我们使用范围条件查询数据时,InnoDB 会锁定这个范围内的数据。比如id有4条数据:1、3、5、7,我们查找1-7范围内的数据。然后 1-7 将被锁定。 2、4、6 也在 1-7 的范围内表行锁定的时候能查询么,但是没有这些数据记录,这些 2、4、6 被称为间隙。间隙锁的危害

当搜索一个范围时,整个范围内的所有数据都会被锁定。甚至一些在这个范围内不存在的数据也会被无辜锁定。例如,如果我想 1、3、< 将 2 插入 @5、7。此时1-7被锁定,2根本无法插入。在某些场景下,它会对性能产生很大的影响。间隙锁演示

我们先将a字段的值修改为1、3、5、7、9窗口A更新a=1~7范围内的数据

更新 test_innodb_lock set b='b5' where a>1 and a

插入 test_innodb_lock 值(2, "b6");

此时发现窗口B中更新a=2的操作一直在等待,因为1~7范围内的数据被gap lock锁住了。只有窗口A执行commit,才能成功更新窗口B的a=2

行锁分析执行SQL分析命令

显示类似“innodb_row_lock%”的状态;

Variable_name 描述 Innodb_row_lock_current_waits:当前等待锁的数量。

innodb_row_lock_time:自系统启动以来锁定的持续时间。

Innodb_row_lock_time_avg:每次等待锁的平均时间。

innodb_row_lock_time_max:系统启动以来最长的锁等待时间。

innodb_row_lock_waits:系统启动后等待锁的总次数。

结论

可以根据Variable_name的参数考虑是否优化。如果加锁时间和加锁次数太大,那么是时候考虑优化了。优化方法请参考上一篇关于索引优化的文章。

老哥

在大厂做高级Java开发的程序员微信搜索:IT大哥,获取更多学习资料

索引 sql优化 mysql索引