mysql锁表分析

因为近期MYSQL在改表移库时,发生了锁表现象.现在对该现象进行分析,并提出一些建议。

一、改表

Mysql 5.6 虽然引入了Online DDL,但是并不是修改表结构的时候,一定不会导致锁表,在一些场景下还是会锁表的,比如
1)某个慢SQL或者比较大的结果集的SQL在运行,执行ALTER TABLE时将会导致锁表发生;
2)存在一个事务在操作表的时候,执行ALTER TABLE也会导致修改等待;

 

按如下步骤执行测试:

1)开启A事务,更新数据,且不提交

3cb1a26f905aa5167b32e68cade7bc76f90.jpg

执行结果如下:

91a922157ab30c856b6032b98ea76bc66c6.jpg

2)开启B事务,更新数据,且不提交

b517e7a76b8c9a6ffc23c9d7a4128221937.jpg

71168ba47188d23d26ee5836c7254370715.jpg

这两条语句互相不影响,将这两个事务回滚掉,继续下一轮测试。


3)开启C事务,更新数据,且不提交

e12f4bf86f85cc4d4c92c5623ceb4b40cb3.jpg

执行结果如下:

eef624fdb076a155265f0312b7c4be497bc.jpg

  1. 修改表结构

mysql锁表分析_第1张图片

  1. 开启D事务,更新数据

8973753f54f6ee076abeca4bfbf3ea0d776.jpg

执行时会发现表被锁住了.

mysql锁表分析_第2张图片

  1. 将C事务提交或者回滚,这里我选择了回滚

mysql锁表分析_第3张图片

7)C事务释放锁后,D事务更改成功,但是耗时很长。

mysql锁表分析_第4张图片

结论与建议:

在执行alter table 操作时,事务会由并行变为串行,同时只能有一个事务更新表数据。尽量选择流量小的时候执行alter 语句。并且要注意避开跑批等耗时较长的更新操作。在执行时最好先看一下有没有未提交的事务。

 

  • 更新单条语句
    MYSQL的锁是加在索引上的,如果update 语句中的where 未使用到索引,即会锁表。

按如下步骤执行测试:

Dsfp_order_jnl表 busi_serial字段不存在索引。

1)开启A事务,更新数据,且不提交

9f8aac84a385f3ce4cfb33a71ee2f802505.jpg

执行结果如下

b5132ae7a180d09e923eba4d74e8d425f32.jpg

 

2)开启B事务,更新数据,且不提交

ee5b5b656b2e38ad5138947a72db3a54d0a.jpg

mysql锁表分析_第5张图片

B事务更新时锁超时。

结论与建议:

update语句必须使用索引,哪怕是更新很快的操作,不然在并发高时一样会导致问题。

 

 

  • 数据集合使用索引
    mysql对于数据集合使用索引时,存在内部优化策略,当你选择的数据范围较大时,会放弃使用索引,而扫描全表,如果是select for update,update,delete等操作就会锁定全表,影响业务。

范围数据有没有使用索引我们可以使用explain查询。

  1. 较小数据范围

2a51a76e757d2dd3e8a658c18f80ed0969c.jpg

f1ab75817506c55afbb0dfb99ffbd8840e4.jpg

Possible_keys表示查询可能使用哪些索引,key表示mysql决定采用哪个索引对查询进行优化。Type range表示这是一个范围扫描。

  1. 扩大数据范围

104041ee3a9a857cd67e386d6630697a874.jpg

4b0158c20241a88559628437665fe28f21d.jpg

此时虽然可以使用索引,但是mysql最终选择了全表扫描。 type 为all,key为null.

对于查询我们可以强制mysql放弃内部优化,使用我们指定的索引。

  1. 使用强制索引

01fbeaa8e79cac674d26db95f25ce9ede26.jpg

2fb59d4f9c6c216e332c10a2042b1906dc6.jpg

Update 语句与select 语句可以使用相同的处理方式。

  1. 更新不使用强制索引

5f731c543788e62c3a75fde2296313d3d17.jpg

328c6a03893008775516c9e24bdd0b31539.jpg

 

  1. 更细使用强制索引

9a30265ca318f3267f2ee0514f08116ed0c.jpg

ef269df2b5bc8ea92cc36343201fc906c90.jpg

Delete 语句不支持force index语法,我们可以使用limit 语句替代,limit语句会优先使用索引查找数据

  1. Delete不使用limit

b5a3c6bd04c606eca1b32944aa5afbde28e.jpg

a0da5e3c434cdb0623ca44acefed545d4b4.jpg

  1. Delete使用limit

fd1bc764c72f731e8724c5495e03108c921.jpg

结论与建议:

在对批量数据进行操作时,先到生产环境或者1b1环境,对要执行的SQL进行一次explain看是否使用了索引。 select for update,update 可以使用force_index。Delete 可以使用limit。

转载于:https://my.oschina.net/u/3944601/blog/3050600

你可能感兴趣的:(数据库)