深入浅出MySQL - MyISAM有趣的那些“锁”事儿

本文详细介绍了MyISAM表锁的工作原理、并发优化技巧,包括表锁的使用场景、并发低下的原因分析,以及如何通过配置参数和SQL优化来提升并发性能。同时讨论了InnoDB与MyISAM在并发控制上的区别,以及MyISAM的concurrent_insert特性。
摘要由CSDN通过智能技术生成

======================================================================

显示加锁方式:

加锁:lock tables … read/write;

– 给T1加读锁

lock tables T1 read;

– 给T1加写锁

lock tables T1 write;

– 给T1加读锁、T2加写锁;

lock tables T1 read, T2 write;

释放锁:unlock tables;

unlock tables;

与 全局锁 FTWRL 类似,可以用 unlock tables 主动释放锁,也可以在客户端断开的时候自动释放。

全局锁:Flush tables with read lock (FTWRL)

这个命令可以使整个库处于只读状态。使用该命令之后,数据更新语句、数据定义语句和更新类事务的提交语句等操作都会被阻塞。

使用场景:全库逻辑备份。

MyISAM在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执行DML操作(UPDATE、DELETE、INSERT等)前,会自动给涉及的表加写锁,这个过程并不需要用户干预,因此,用户一般不需要直接用LOCK TABLE命令给MyISAM表显式加锁,可以根据具体业务场景修改其加锁配置。

三、MyISAM表锁并发优化

=============================================================================

在使用MyISAM存储引擎前,我们要确认选择该引擎的原因,比如该表并发读较多,写操作较少(如用户表、日志表等),如果是由于DML(增删改)操作都较多造成并发低,建议直接改用Innodb引擎。

表锁在实现的过程中比行锁定或者页锁所带来的附加成本都要小,锁定本身所消耗的资源也是最少,毕竟是直接锁表。但由于锁定的颗粒度大,因此造成锁定资源的争用情况也会比其他的锁定级别都要多,在较大程度上会降低并发处理能力。

所以,当优化MyISAM存储引擎锁定问题时,重点还要放在提升单事务并发速度上。由于表级别锁是不可能改变的了,因此我们要着眼于尽可能让锁定的时间变短,事务间能尽快释放锁,从而提升并发。可以通过show status like 'table%'命令来排查表锁并发情况

mysql> show status like 'table%;

±---------------------------±--------+

| Variable_name | Value |

±---------------------------±--------+

| Table_locks_immediate | 1000 |

| Table_locks_waited | 80 |

±---------------------------±--------+

参数讲解:

  • Table_locks_immediate:产生表锁的次数;

  • Table_locks_waited:出现表锁争用而发生等待的次数;

两个状态值都是从系统启动后开始记录,出现一次对应的事件则数量加1。如果排查时发现这里的Table_locks_waited状态值较高,那么说明系统中表级锁定争用现象比较严重,就要着手于如何减少表锁等待次数了。优化方式又来到我们强项了:SQl优化、分库分表、减少复杂SQL、缩印利用率等(干货太多找不到?推荐收藏《MySQL江湖路 | 专栏目录》)。

另外MyISAM还有两个有趣有用的知识点:

1、自定义读写操作优先级!


福音!当我第一次发现这个策略配置时,心情十分激动,脑海中各种腹黑操作接踵而至~~

我有一个同事小田,经常看我文章的朋友可能会有印象。我俩关系可不一般,怎么形容呢?每天早上见到他,脑子里闪过的场景都是:“叶问一巴掌呼倒日本武士”、“钢铁侠一拳干飞金刚狼”、“腕豪大招把大虫子抱进泉水” 那种酣畅淋漓的场面。

在这里插入图片描述

实际场景是这样的:每天上午9点我和他都会有脚本对某张APP应用大表的不同字段数据进行UPDATE操作和部分INSERT操作。我发现如果只有我的脚本运行10分钟就跑完了,但是和他的脚本一起跑就需要半小时!

我凑!赶紧看看如何能把我的chenhh用户操作优先级提到最高,把tiantian这个垃圾用户优先级调到0!干tm的!

在这里插入图片描述

结果却是令人失望的。。

  1. 配置优先级只有MyISAM引擎可以,我们的表是Innodb;

  2. MyISAM只能自定义配置读、写操作的相对优先级,无法配置不同用户间的优先级。。。

MySQL连这功能都没有吗?这TM得优化啊!唉,腹黑的复仇计划再次泡汤,新的认知层次并不能改变我的现状。。或许,还是我太过天真,像孩子一样无助??卧槽什么歌来着?

在这里插入图片描述

言归正传,MyISAM当读写操作同时出现时,MySQL默认优先执行写操作。那如果一直写,那些读线程不就完蛋了?MySQL针对这类问题增加了变量max_write_lock_count控制最大写锁数量上限,同学们可以自己根据实际环境配置这个最大锁等待值达到峰值后,MySQL会自动降低写操作优先级,等这个数量的写操作执行完后,会先把等待读(等待写锁释放)的请求队列中的事务优先处理掉,然后再继续写。

手动控制方法:

- 通过系统变量配置

系统变量配置:通过SET LOW_PRIORITY_UPDATES=ON命令,降低写操作优先级低于读

mysql> show variables like ‘%LOW_PRIORITY%’;

±---------------------±------+

| Variable_name | Value |

±---------------------±------+

| low_priority_updates | OFF |

±---------------------±------+

1 row in set (0.01 sec)

mysql> SET LOW_PRIORITY_UPDATES=ON;

Query OK, 0 rows affected (0.00 sec)

mysql> show variables like ‘%LOW_PRIORITY%’;

±---------------------±------+

| Variable_name | Value |

±---------------------±------+

| low_priority_updates | ON |

±---------------------±------+

1 row in set (0.00 sec)

- 在SQL语句中配置

在SQL语句中临时配置:只对该SQL有效

提高优先级操作关键字HIGH_PRIORITY,HIGH_PRIORITY可以使用在SELECT和INSERT操作中,让MYSQL知道,这个读操作优先进行。

SELECT HIGH_PRIORITY * FROM T;

降低优先级操作关键字LOW_PRIORITY,LOW_PRIORITY可以使用在INSERT、UPDATE、REPLACE、DELETE 以及 LOAD DATA 等操作中,让mysql知道,这个操作优先级较低。

update LOW_PRIORITY T set money +=10000000 where name = ‘陈哈哈’ ;

需要注意的是,如果耗时很长的慢查询(读事务)较多,也会把写进程“饿死”,因此在我们涉及到配置SQL执行优先级时,一定要控制好读(SELECT)进程的执行效率。针对一些(复杂度高或查询量大)且难以优化的SELECT语句,俗称“硬伤”,针对这些硬伤我建议对业务进行一定的拆分,降低复杂度后处理,或者如果是非必要精确的统计数据,可以加个EVENT事件,比如每10分钟更新一下结果集存到一个表中,然后使用时直接取,这个我们叫数据报表

2、并发插入


一提到MyISAM的表锁,我们立即反应过来的就是串行化,但是我们可以思考一下,如果写操作是一堆insert语句的话,是否还必须串行化?

这里我们要提到一个MySQL特性:concurrent_insert(并发插入)

MyISAM存储引擎有一个控制是否打开concurrent_insert功能的参数选项:concurrent_insert,可以设置为0、1、2:

  • concurrent_insert=2,无论MyISAM表中有没有空洞,都允许在表尾并发插入记录;

  • concurrent_insert=1,如果MyISAM表中没有空洞(即表的中间没有被删除的行),MyISAM允许在一个进程读表的同时,另一个进程从表尾插入记录。这也是MySQL的默认设置;

  • concurrent_insert=0,不允许并发插入,串行。

concurrent_insert=1(默认):Mysql 5.5.2前显示为1;从5.5.3版本开始concurrent_insert=1参数用枚举值默认为AUTO,concurrent_insert=2 为ALWAYS

mysql> show variables like ‘%Concurrent%’;

±------------------±------+

| Variable_name | Value |

±------------------±------+

| concurrent_insert | AUTO |

±------------------±------+

1 row in set (0.01 sec)

mysql> set GLOBAL concurrent_insert=2;

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

总结

面试前的“练手”还是很重要的,所以开始面试之前一定要准备好啊,不然也是耽搁面试官和自己的时间。

我自己是刷了不少面试题的,所以在面试过程中才能够做到心中有数,基本上会清楚面试过程中会问到哪些知识点,高频题又有哪些,所以刷题是面试前期准备过程中非常重要的一点。

面试题及解析总结

三年Java开发,刚从美团、京东、阿里面试归来,分享个人面经

大厂面试场景

三年Java开发,刚从美团、京东、阿里面试归来,分享个人面经

知识点总结

三年Java开发,刚从美团、京东、阿里面试归来,分享个人面经

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
面试过程中才能够做到心中有数,基本上会清楚面试过程中会问到哪些知识点,高频题又有哪些,所以刷题是面试前期准备过程中非常重要的一点。

面试题及解析总结

[外链图片转存中…(img-DVWsi9z1-1713747933242)]

大厂面试场景

[外链图片转存中…(img-ssK7h1o3-1713747933242)]

知识点总结

[外链图片转存中…(img-wnFu4BVN-1713747933242)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 30
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值