mysql数据库多个会话在慢查询中的表现

通过故意构造一些慢查询,看看两个会话之间的互相影响。

 

一 测试的初始环境

创建一个测试表

CREATE TABLE `test1` (

  `id` int(11) DEFAULT NULL,

  `n1` varchar(255) DEFAULT NULL

) ENGINE=InnoDB DEFAULT CHARSET=latin1;

 

一开始表中有5行数据:

1       a

2       b

3       c

4       d

5       e

 

 

测试1

会话A中开启一个慢查询

[SQL]select * from test1 where sleep(1)=0;

受影响的行: 0

时间: 5.003s

 

在执行每一行时停1s,共5行,所以总执行时间5秒多一点。

 

会话A:

select * from test1 where sleep(2)=0;

会话B中尝试进行修改操作

update test1 set n1=CONCAT(n1,'-t') where id = 1;

 

发现会话B的修改操作不会被会话A阻塞

 

会话A:

select * from test1 where sleep(2)=0 for update;

会话B中尝试进行修改操作

[SQL]update test1 set n1=CONCAT(n1,'-t') where id = 1;

受影响的行: 1

时间: 7.646s

可以看到会话B被会话A阻塞了,移动鼠标从会话A切换到会话用了两秒多。

 

 

会话A:

begin;

select * from test1 where sleep(10)=0 for update;

commit;会话B中尝试进行修改操作

 

 

查看被锁住的表:

show open tables where in_use>0;

 

[SQL]update test1 set n1=CONCAT(n1,'-t') where id = 1;

受影响的行: 1

 

时间: 47.399s

 

可以看到会话B被会话A阻塞了

 

会话A:

select count(*) from test1 where sleep(2)=0;

 

会话B中尝试进行修改操作

[SQL]update test1 set n1=CONCAT(n1,'-t') where id = 1;

受影响的行: 1

时间: 0.184s

 

可以看到会话B未被会话A阻塞。

 

会话A:

select count(*) from test1 where sleep(2)=0;

 

会话B中尝试进行插入操作

[SQL]insert into test1(id,n1) values(6,'f');

受影响的行: 1

时间: 0.201s

 

可以看到会话B未被会话A阻塞。

 

小结一下:如果慢查询不带 for update 便不会阻塞修改操作

 

 

开启慢查询日志:

show variables like 'slow_query%';

show variables like 'long_query_time';

set global slow_query_log='ON';

 

 

执行以上的慢查询后检查慢查询日志文件,看到如下的结果

 

Mysql5.5, Version: 5.5.33-log (MySQL Community Server (GPL)). started with:

TCP Port: 3306, Named Pipe: /tmp/mysql.sock

Time                 Id Command    Argument

# Time: 181218 19:17:39

# User@Host: root[root] @ localhost [127.0.0.1]

# Query_time: 14.003255  Lock_time: 0.000000 Rows_sent: 1  Rows_examined: 7

use test;

SET timestamp=1545131859;

select count(*) from test1 where sleep(2)=0;

 

 

可见确实产生了一个慢查询记录。

 

特地将mysql服务关闭后又重新启动,发现慢查询日志文件保持不变。也就是说重启mysql服务不会自动删除慢查询日志文件。

 

 

 

测试2

会话A: 是一个很慢的修改数据操作

[SQL]update test1 set n1=CONCAT(n1,'-t') where sleep(2)=0;

受影响的行: 7

时间: 14.112s;

 

会话B中尝试进行求记录数

[SQL]

select count(*) from test1 ;

受影响的行: 0

时间: 0.000s

 

 

可以看到会话B未被会话A阻塞。

 

 

会话A: 是一个很慢的修改数据操作

[SQL]update test1 set n1=CONCAT(n1,'-t') where sleep(2)=0;

受影响的行: 7

时间: 14.112s;

 

会话B中尝试进行求记录数

[SQL]

select count(*) from test1 where n1>'';

受影响的行: 0

时间: 0.001s

 

可以看到会话B未被会话A阻塞。

 

 

查看慢查询日志文件:

Mysql5.5, Version: 5.5.33-log (MySQL Community Server (GPL)). started with:

TCP Port: 3306, Named Pipe: /tmp/mysql.sock

Time                 Id Command    Argument

# Time: 181218 19:17:39

# User@Host: root[root] @ localhost [127.0.0.1]

# Query_time: 14.003255  Lock_time: 0.000000 Rows_sent: 1  Rows_examined: 7

use test;

SET timestamp=1545131859;

select count(*) from test1 where sleep(2)=0;

Mysql5.5, Version: 5.5.33-log (MySQL Community Server (GPL)). started with:

TCP Port: 3306, Named Pipe: /tmp/mysql.sock

Time                 Id Command    Argument

# Time: 181218 19:48:22

# User@Host: root[root] @ localhost [127.0.0.1]

# Query_time: 14.010628  Lock_time: 0.000000 Rows_sent: 0  Rows_examined: 7

use test;

SET timestamp=1545133702;

update test1 set n1=CONCAT(n1,'-t') where sleep(2)=0;

# Time: 181218 19:48:36

# User@Host: root[root] @ localhost [127.0.0.1]

# Query_time: 14.010784  Lock_time: 0.000000 Rows_sent: 0  Rows_examined: 7

SET timestamp=1545133716;

update test1 set n1=CONCAT(n1,'-t') where sleep(2)=0;

 

确实看到update操作用时14s多。

 

小结一下: 尽管有一个很慢的修改操作正在更新数据表,但不会因此而阻塞查询操作。

 

 

测试3

会话A: 是一个很慢的修改数据操作

[SQL]update test1 set n1=CONCAT(n1,'-t') where sleep(2)=0;

受影响的行: 7

时间: 14.229s

 

会话B中尝试进行求记录数,并且带上了For update

[SQL]

[SQL]select count(*) from test1 where n1>'' for update;

受影响的行: 0

时间: 11.532s

 

可以看到会话B被会话A阻塞。

 

会话A 一个很慢的查询求最大值,并且带有for update

[SQL]select max(id) from test1  where SLEEP(2) = 0 for update;

受影响的行: 0

时间: 14.003s

 

会话B 一个很慢的查询求最大值,并且带有for update

[SQL]select max(id) from test1  where SLEEP(2) = 0 for update;

受影响的行: 0

时间: 25.115s

 

可以看到会话B被会话A阻塞。

 

会话A 一个很慢的查询求最大值,并且带有for update

[SQL]select max(id) from test1  where SLEEP(2) = 0 for update;

受影响的行: 0

时间: 14.003s

 

会话B 一个很慢的查询求最大值,不带for update

[SQL]select max(id) from test1  where SLEEP(2) = 0

 

受影响的行: 0

时间: 14.004s

 

可以看到会话B没有被会话A阻塞。

 

 

 

会话A 一个很慢的查询求最大值,并且带有for update

[SQL]select max(id) from test1  where SLEEP(2) = 0 for update;

受影响的行: 0

时间: 14.005s

 

 

会话B: 是一个修改数据操作

[SQL]update test1 set n1=CONCAT(n1,'-t') where id = 1;

受影响的行: 1

时间: 11.956s

 

会话C中尝试进行求记录数,并且带上了For update

[SQL]select max(id) from test1  where SLEEP(2) = 0 for update;

受影响的行: 0

时间: 23.801s

 

 

可以看到会话B被会话A阻塞,会话C被会话A,B阻塞。会话c的阻塞时间差不多是A,C执行时间之和。

 

小结一下:慢查询如果带 for update 便会阻塞其后的带for update的查询操作以及修改操作。不带for update的查询不会被阻塞。

猜你喜欢

转载自blog.csdn.net/littlezhuhui/article/details/85120516