暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

MySQL sleep() 的妙用。

原创 aisql 2022-12-08
4625

1、MySQL 提供了 睡眠函数sleep

官方介绍如下:

SLEEP(duration)

Sleeps (pauses) for the number of seconds given by the duration argument, then returns 0. The duration may have a fractional part. If the argument is NULL or negative, SLEEP() produces a warning, or an error in strict SQL mode.

When sleep returns normally (without interruption), it returns 0

妙用一: 用在select 语句中

sleep 可以用于 select 字段处与where 处

比如:

select sleep(10),field1,field2 from t; select field1 from t where sleep(20);

有了这个操作之后,我们有时候模拟慢查询就方便多了。

我在实际业务中有以下两种情况用到了sleep函数

a、模拟慢查询以复现生产中 查询慢造成的并发问题

在session1中 执行
select sleep(10),field1 from t

在session2中 执行 你需要模拟的并发语句,update、delete、ddl语句

你就可以复现 元数据锁的等待时间了。是必须整个select 语句执行完,ddl才能拿到元数据锁执行

这么写的好处是你可以决定慢查询要执行的时间。

b、解决开发在写参数化语句过程中不好跟踪的问题

有时后端开发参数化的语句不好跟踪。总是认为是MySQL的bug 为了看到最终的语句。我让开发在select 语句中加上sleep,然后在慢查询日志中就很快能找到此语句了。

妙用二: 用在update语句中

前几天在研究当表结构都没有索引的时候,udpate语句执行锁的情况。利用到了sleep特性

下面花一点篇幅来说说整个过程

在RC隔离级别下。无索引的update 执行情况

将当前session换为RC级别,并确认

set session transaction isolation level read committed; select @@transaction_isolation;

创建测试表并构建基础数据

CREATE TABLE `billno` ( `tid` int(10) unsigned NOT NULL, `billtype` int(10) unsigned NOT NULL COMMENT '单据类型ID', `datas` int(10) unsigned NOT NULL COMMENT '如果永不归零则为0,如果跨年则为年份2016 ,如果跨月则为201601,如果跨日则为20160103', `maxno` int(10) unsigned NOT NULL COMMENT '当前系统里面最大的单据ID' ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='单据编号生成表'; insert into billno values(1,1,1,1),(2,2,2,2),(3,3,3,3),(4,4,4,4) ,(5,5,5,5),(6,6,6,6),(7,7,7,7),(8,8,8,8) ,(9,9,9,9); ALTER TABLE `billno` ADD PRIMARY KEY (`tid`,`billtype`,`datas`);

然后执行一个update语句,利用sleep特性。让每行都执行得很慢 让每行都执行很慢。这个很关键

session1中执行

update billno set tid =19 where sleep(20) or maxno =9

然后在session2中 每隔几秒执行一次查询

select * from performance_schema.data_locks;

第一次查
image.png

第二次查
image.png
最后一次查

image.png

可以从上面的结果看出 当没有索引的情况找到符合条件的行时候 在RC情况下是这一行没有最终修改 那么将很快释放掉锁。

我们把session1语句改这样
session1中执行

update billno set tid =19 where sleep(20) and maxno =9

又在 session2中查询

select * from performance_schema.data_locks;

image.png

当在RC级别下。最终只会锁符合where 条件的行,不符合条件的行只会在扫描的时候短暂加一下锁。

在RR隔离级别下。无索引的update 执行情况

set session transaction isolation level read committed; select @@transaction_isolation;

同样的语句。只是隔离级别换成了RR
session1中执行

update billno set tid =19 where sleep(20) or maxno =9

然后在session2中 每隔几秒执行一次查询

select * from performance_schema.data_locks;

第一次查
image.png
第二次查
image.png
最后一次查
image.png

可以从上面的结果看出 当没有索引的情况找到符合条件的行时候 在RR情况下扫描的每行都加上了锁,直到语句结束。

再来测试第二个语句
session1中执行

update billno set tid =19 where sleep(20) and maxno =9

同样在session2中查询
image.png

可以从上面的结果看出 当没有索引的情况即使条件不符合 在RR情况下扫描的每行都加上了锁,直到语句结束。

结论 可以看到RR级别的锁明显多于RC 所以生产环境不是必须要RR那就用RC吧

最后修改时间:2023-09-15 17:48:10
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论