iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >MySQL在并发场景下的问题及解决思路是怎样的
  • 216
分享到

MySQL在并发场景下的问题及解决思路是怎样的

2024-04-02 19:04:59 216人浏览 安东尼
摘要

本篇文章为大家展示了Mysql在并发场景下的问题及解决思路是怎样的,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。1、背景对于数据库系统来说在多用户并发条件下提高并发

本篇文章为大家展示了Mysql并发场景下的问题及解决思路是怎样的,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

1、背景

对于数据库系统来说在多用户并发条件下提高并发性的同时又要保证数据的一致性一直是数据库系统追求的目标,既要满足大量并发访问的需求又必须保证在此条件下数据的安全,为了满足这一目标大多数数据库通过事务机制来实现,mysql数据库也不例外。尽管如此我们仍然会在业务开发过程中遇到各种各样的疑难问题,本文将以案例的方式演示常见的并发问题并分析解决思路。

2、表锁导致的慢查询的问题

首先我们看一个简单案例,根据ID查询一条用户信息

mysql> select * from user where id=6;

这个表的记录总数为3条,但却执行了13秒。

MySQL在并发场景下的问题及解决思路是怎样的

出现这种问题我们首先想到的是看看当前MySQL进程状态:

MySQL在并发场景下的问题及解决思路是怎样的

从进程上可以看出select语句是在等待一个表锁,那么这个表锁又是什么查询产生的呢?这个结果中并没有显示直接的关联关系,但我们可以推测多半是那条update语句产生的(因为进程中没有其他可疑的SQL),为了印证我们的猜测,先检查一下user表结构:

MySQL在并发场景下的问题及解决思路是怎样的

果然user表使用了MyISAM存储引擎,MyISAM在执行操作前会产生表锁,操作完成再自动解锁。如果操作是写操作,则表锁类型为写锁,如果操作是读操作则表锁类型为读锁。正如和你理解的一样写锁将阻塞其他操作(包括读和写),这使得所有操作变为串行;而读锁情况下读-读操作可以并行,但读-写操作仍然是串行。以下示例演示了显式指定了表锁(读锁),读-读并行,读-写串行的情况。

显式开启/关闭表锁,使用lock table user read/write; unlock tables;

session1:

MySQL在并发场景下的问题及解决思路是怎样的

session2:

MySQL在并发场景下的问题及解决思路是怎样的

可以看到会话1启用表锁(读锁)执行读操作,这时会话2可以并行执行读操作,但写操作被阻塞。接着看:

session1:

MySQL在并发场景下的问题及解决思路是怎样的

session2:

MySQL在并发场景下的问题及解决思路是怎样的

当session1执行解锁后,seesion2则立刻开始执行写操作,即读-写串行。

总结:

到此我们把问题的原因基本分析清楚,总结一下——MyISAM存储引擎执行操作时会产生表锁,将影响其他用户对该表的操作,如果表锁是写锁,则会导致其他用户操作串行,如果是读锁则其他用户的读操作可以并行。所以有时我们遇到某个简单的查询花了很长时间,看看是不是这种情况。

解决办法:

1)尽量不用MyISAM存储引擎,在MySQL8.0版本中已经去掉了所有的MyISAM存储引擎的表,推荐使用InnoDB存储引擎。

2)如果一定要用MyISAM存储引擎,减少写操作的时间;

3、线上修改表结构有哪些风险?

如果有一天业务系统需要增大一个字段长度,能否在线上直接修改呢?在回答这个问题前,我们先来看一个案例:

MySQL在并发场景下的问题及解决思路是怎样的

以上语句尝试修改user表的name字段长度,语句被阻塞。按照惯例,我们检查一下当前进程:

MySQL在并发场景下的问题及解决思路是怎样的

从进程可以看出alter语句在等待一个元数据锁,而这个元数据锁很可能是上面这条select语句引起的,事实正是如此。在执行DML(select、update、delete、insert)操作时,会对表增加一个元数据锁,这个元数据锁是为了保证在查询期间表结构不会被修改,因此上面的alter语句会被阻塞。那么如果执行顺序相反,先执行alter语句,再执行DML语句呢?DML语句会被阻塞吗?例如我正在线上环境修改表结构,线上的DML语句会被阻塞吗?答案是:不确定。

在MySQL5.6开始提供了online ddl功能,允许一些DDL语句和DML语句并发,在当前5.7版本对online ddl又有了增强,这使得大部分DDL操作可以在线进行。详见:https://dev.mysql.com/doc/refman/5.7/en/innodb-create-index-overview.html

所以对于特定场景执行DDL过程中,DML是否会被阻塞需要视场景而定。

总结:通过这个例子我们对元数据锁和online ddl有了一个基本的认识,如果我们在业务开发过程中有在线修改表结构的需求,可以参考以下方案:

1. 尽量在业务量小的时间段进行;

2. 查看官方文档,确认要做的表修改可以和DML并发,不会阻塞线上业务;

3. 推荐使用percona公司的pt-online-schema-change工具,该工具被官方的online ddl更为强大,它的基本原理是:通过insert… select…语句进行一次全量拷贝,通过触发器记录表结构变更过程中产生的增量,从而达到表结构变更的目的。

例如要对A表进行变更,主要步骤为:

创建目的表结构的空表,A_new;

在A表上创建触发器,包括增、删、改触发器;

通过insert…select…limit N 语句分片拷贝数据到目的表

Copy完成后,将A_new表rename到A表。

4、一个死锁问题的分析

在线上环境下死锁的问题偶有发生,死锁是因为两个或多个事务相互等待对方释放锁,导致事务永远无法终止的情况。为了分析问题,我们下面将模拟一个简单死锁的情况,然后从中总结出一些分析思路。

演示环境:MySQL5.7.20 事务隔离级别:RR

表user:

CREATE TABLE `user` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `name` varchar(300) DEFAULT NULL,  `age` int(11) DEFAULT NULL,  PRIMARY KEY (`id`)  ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8

下面演示事务1、事务2工作的情况: 

 

事务1

事务2

事务监控

T1

begin;

Query OK, 0 rows affected (0.00 sec)

begin;

Query OK, 0 rows affected (0.00 sec)

 
T2

select * from user where id=3 for update;

+----+------+------+
| id | name | age |
+----+------+------+
| 3 | sun | 20 |
+----+------+------+
1 row in set (0.00 sec)

select * from user where id=4 for update;

+----+------+------+
| id | name | age |
+----+------+------+
| 4 | zhou | 21 |
+----+------+------+
1 row in set (0.00 sec)

select * from infORMation_schema.INNODB_TRX;

通过查询元数据库innodb事务表,监控到当前运行事务数为2,即事务1、事务2。

T3

update user set name='haha' where id=4;

因为id=4的记录已被事务2加上行锁,该语句将阻塞

 监控到当前运行事务数为2。
T4阻塞状态

update user set name='hehe' where id=3;

ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

id=3的记录已被事务1加上行锁,而本事务持有id=4的记录行锁,此时InnoDB存储引擎检查出死锁,本事务被回滚。

事务2被回滚,事务1仍在运行中,监控当前运行事务数为1。
T5

Query OK, 1 row affected (20.91 sec)
Rows matched: 1 Changed: 1 Warnings: 0

由于事务2被回滚,原来阻塞的update语句被继续执行。

 监控当前运行事务数为1。
T6

commit;

Query OK, 0 rows affected (0.00 sec)

 事务1已提交、事务2已回滚,监控当前运行事务数为0。

这是一个简单的死锁场景,事务1、事务2彼此等待对方释放锁,InnoDB存储引擎检测到死锁发生,让事务2回滚,这使得事务1不再等待事务B的锁,从而能够继续执行。那么InnoDB存储引擎是如何检测到死锁的呢?为了弄明白这个问题,我们先检查此时InnoDB的状态:

show engine innodb status\G   ------------------------  LATEST DETECTED DEADLOCK  ------------------------  2018-01-14 12:17:13 0x70000f1cc000  *** (1) TRANSACTION:  TRANSACTION 5120, ACTIVE 17 sec starting index read  mysql tables in use 1, locked 1  LOCK WaiT 3 lock struct(s), heap size 1136, 2 row lock(s)  MySQL thread id 10, OS thread handle 123145556967424, query id 2764 localhost root updating  update user set name='haha' where id=4  *** (1) WAITING FOR THIS LOCK TO BE GRANTED:  RECORD LOCKS space id 94 page no 3 n bits 80 index PRIMARY of table `test`.`user` trx id 5120 lock_mode X locks rec but not gap waiting  Record lock, heap no 5 PHYSICAL RECORD: n_fields 5; compact format; info bits 0  0: len 4; hex 80000004; asc ;;  1: len 6; hex 0000000013fa; asc ;;  2: len 7; hex 520000060129a6; asc R ) ;;  3: len 4; hex 68616861; asc haha;;  4: len 4; hex 80000015; asc ;;  *** (2) TRANSACTION:  TRANSACTION 5121, ACTIVE 12 sec starting index read  mysql tables in use 1, locked 1  3 lock struct(s), heap size 1136, 2 row lock(s)  MySQL thread id 11, OS thread handle 123145555853312, query id 2765 localhost root updating  update user set name='hehe' where id=3  *** (2) HOLDS THE LOCK(S):  RECORD LOCKS space id 94 page no 3 n bits 80 index PRIMARY of table `test`.`user` trx id 5121 lock_mode X locks rec but not gap  Record lock, heap no 5 PHYSICAL RECORD: n_fields 5; compact format; info bits 0  0: len 4; hex 80000004; asc ;;  1: len 6; hex 0000000013fa; asc ;;  2: len 7; hex 520000060129a6; asc R ) ;;  3: len 4; hex 68616861; asc haha;;  4: len 4; hex 80000015; asc ;;  *** (2) WAITING FOR THIS LOCK TO BE GRANTED:  RECORD LOCKS space id 94 page no 3 n bits 80 index PRIMARY of table `test`.`user` trx id 5121 lock_mode X locks rec but not gap waiting  Record lock, heap no 7 PHYSICAL RECORD: n_fields 5; compact format; info bits 0  0: len 4; hex 80000003; asc ;;  1: len 6; hex 0000000013fe; asc ;;  2: len 7; hex 5500000156012f; asc U V /;;  3: len 4; hex 68656865; asc hehe;;  4: len 4; hex 80000014; asc ;;  *** WE ROLL BACK TRANSACTION (2)

InnoDB状态有很多指标,这里我们截取死锁相关的信息,可以看出InnoDB可以输出最近出现的死锁信息,其实很多死锁监控工具也是基于此功能开发的。

在死锁信息中,显示了两个事务等待锁的相关信息(蓝色代表事务1、绿色代表事务2),重点关注:WAITING FOR THIS LOCK TO BE GRANTED和HOLDS THE LOCK(S)。

WAITING FOR THIS LOCK TO BE GRANTED表示当前事务正在等待的锁信息,从输出结果看出事务1正在等待heap no为5的行锁,事务2正在等待 heap no为7的行锁;

HOLDS THE LOCK(S):表示当前事务持有的锁信息,从输出结果看出事务2持有heap no为5行锁。

从输出结果看出,***InnoDB回滚了事务2。

那么InnoDB是如何检查出死锁的呢?

我们想到最简单方法是假如一个事务正在等待一个锁,如果等待时间超过了设定的阈值,那么该事务操作失败,这就避免了多个事务彼此长等待的情况。参数innodb_lock_wait_timeout正是用来设置这个锁等待时间的。

如果按照这个方法,解决死锁是需要时间的(即等待超过innodb_lock_wait_timeout设定的阈值),这种方法稍显被动而且影响系统性能,InnoDB存储引擎提供一个更好的算法来解决死锁问题,wait-for graph算法。简单的说,当出现多个事务开始彼此等待时,启用wait-for graph算法,该算法判定为死锁后立即回滚其中一个事务,死锁被解除。该方法的好处是:检查更为主动,等待时间短。

下面是wait-for graph算法的基本原理:

为了便于理解,我们把死锁看做4辆车彼此阻塞的场景:

 MySQL在并发场景下的问题及解决思路是怎样的

MySQL在并发场景下的问题及解决思路是怎样的

4辆车看做4个事务,彼此等待对方的锁,造成死锁。wait-for graph算法原理是把事务作为节点,事务之间的锁等待关系,用有向边表示,例如事务A等待事务B的锁,就从节点A画一条有向边到节点B,这样如果A、B、C、D构成的有向图,形成了环,则判断为死锁。这就是wait-for graph算法的基本原理。

总结:

1. 如果我们业务开发中出现死锁如何检查出?刚才已经介绍了通过监控InnoDB状态可以得出,你可以做一个小工具把死锁的记录收集起来,便于事后查看。

2. 如果出现死锁,业务系统应该如何应对?从上文我们可以看到当InnoDB检查出死锁后,对客户端报出一个Deadlock found when trying to get lock; try restarting transaction信息,并且回滚该事务,应用端需要针对该信息,做事务重启的工作,并保存现场日志事后做进一步分析,避免下次死锁的产生。

5、锁等待问题的分析

在业务开发中死锁的出现概率较小,但锁等待出现的概率较大,锁等待是因为一个事务长时间占用锁资源,而其他事务一直等待前个事务释放锁。

 

事务1

事务2

事务监控

T1

begin;

Query OK, 0 rows affected (0.00 sec)

begin;

Query OK, 0 rows affected (0.00 sec)

 
T2

select * from user where id=3 for update;

+----+------+------+
| id | name | age |
+----+------+------+
| 3 | sun | 20 |
+----+------+------+
1 row in set (0.00 sec)

其他查询操作

select * from information_schema.INNODB_TRX;

通过查询元数据库innodb事务表,监控到当前运行事务数为2,即事务1、事务2。

T3 其他查询操作

 update user set name='hehe' where id=3;

因为id=3的记录被事务1加上行锁,所以该语句将阻塞(即锁等待)

 监控到当前运行事务数为2。
T4其他查询操作

ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

锁等待时间超过阈值,操作失败。注意:此时事务2并没有回滚。

监控到当前运行事务数为2。
T5commit; 事务1已提交,事务2未提交,监控到当前运行事务数为1。

从上述可知事务1长时间持有id=3的行锁,事务2产生锁等待,等待时间超过innodb_lock_wait_timeout后操作中断,但事务并没有回滚。如果我们业务开发中遇到锁等待,不仅会影响性能,还会给你的业务流程提出挑战,因为你的业务端需要对锁等待的情况做适应的逻辑处理,是重试操作还是回滚事务。

在MySQL元数据表中有对事务、锁等待的信息进行收集,例如information_schema数据库下的INNODB_LOCKS、INNODB_TRX、INNODB_LOCK_WAITS,你可以通过这些表观察你的业务系统锁等待的情况。你也可以用一下语句方便的查询事务和锁等待的关联关系:

SELECT r.trx_id waiting_trx_id,r.trx_mysql_thread_id waiting_thread,r.trx_query wating_query, b.trx_id blocking_trx_id,b.trx_mysql_thread_id blocking_thread,b.trx_query blocking_query FROM information_schema.innodb_lock_waits w  INNER JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id  INNER JOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id;

结果:

waiting_trx_id: 5132 waiting_thread: 11 wating_query: update user set name='hehe' where id=3 blocking_trx_id: 5133 blocking_thread: 10 blocking_query: NULL

总结:

1. 请对你的业务系统做锁等待的监控,这有助于你了解当前数据库锁情况,以及为你优化业务程序提供帮助;

2. 业务系统中应该对锁等待超时的情况做合适的逻辑判断。

上述内容就是MySQL在并发场景下的问题及解决思路是怎样的,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注编程网数据库频道。

您可能感兴趣的文档:

--结束END--

本文标题: MySQL在并发场景下的问题及解决思路是怎样的

本文链接: https://www.lsjlt.com/news/67857.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • MySQL在并发场景下的问题及解决思路是怎样的
    本篇文章为大家展示了MySQL在并发场景下的问题及解决思路是怎样的,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。1、背景对于数据库系统来说在多用户并发条件下提高并发...
    99+
    2024-04-02
  • 分析MySQL并发下的问题及解决方法
    1、背景 对于数据库系统来说在多用户并发条件下提高并发性的同时又要保证数据的一致性一直是数据库系统追求的目标,既要满足大量并发访问的需求又必须保证在此条件下数据的安全,为了满足这一目标大多数数据库通过锁和事...
    99+
    2024-04-02
  • 解决Nginx 400 Bad Request问题的思路是怎样的
    解决Nginx 400 Bad Request问题的思路是怎样的,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。400 Bad Request是一种HTTP错误状态码。HTT...
    99+
    2023-06-04
  • 如何使用php函数解决高并发场景下的性能问题?
    高并发场景是指系统在同一时间段内接收到大量的请求。在这种情况下,系统的性能会受到很大的挑战,因为处理大量请求可能会导致服务器响应时间过长,甚至造成系统崩溃。为了解决高并发场景下的性能问题,PHP提供了一些函数和技巧。下面将介绍一些常见的方法...
    99+
    2023-10-21
    PHP性能优化 并发处理 函数调用
  • MySQL在大数据、高并发场景下的SQL语句优化和实践是怎样的
    MySQL在大数据、高并发场景下的SQL语句优化和实践是怎样的,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你...
    99+
    2024-04-02
  • nf_conntrack中table full, dropping packet问题的解决思路是怎样的
    本篇文章为大家展示了nf_conntrack中table full, dropping packet问题的解决思路是怎样的,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。介绍:nf_conntrack...
    99+
    2023-06-13
  • PHP 防抖技术:解决高并发场景下的数据重复提交问题
    导言:在高并发场景中,用户可能会频繁点击按钮或提交表单,这就导致服务器收到多次相同的请求,从而可能造成数据的重复提交。针对这一问题,我们可以采取一种被称为“防抖”的技术来解决。本文将介绍PHP中的防抖技术以及具体的代码示例,旨在帮助开发者们...
    99+
    2023-10-21
    高并发 防抖技术 数据重复提交
  • PHP并发场景的解决方案是什么
    本篇文章给大家分享的是有关PHP并发场景的解决方案是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。在秒杀,抢购等并发场景下,可能会出现超卖...
    99+
    2024-04-02
  • Golang 并发下的问题定位及解决方案
    目录问题描述解决方案实现思路2.1 通过栈信息解析后获取2.2 修改 Go 源码获取2.3 通过 CGO 获取问题描述 在使用 gin-swagger 的过程中, 经常会发生因为缺少...
    99+
    2024-04-02
  • Java高并发场景下的缓存常见的问题有哪些
    这篇文章主要讲解了“Java高并发场景下的缓存常见的问题有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java高并发场景下的缓存常见的问题有哪些”吧!一、缓存一致性问题当数据时效性要求...
    99+
    2023-06-05
  • MySQL事务的ACID特性及并发问题怎么解决
    这篇“MySQL事务的ACID特性及并发问题怎么解决”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“MySQL事务的ACID特...
    99+
    2023-07-02
  • Redis:高并发场景下的数据存储解决方案
    Redis:高并发场景下的数据存储解决方案随着互联网的迅速发展,高并发场景下的数据存储已成为各大企业关注的焦点。在面对海量请求和快速响应的需求时,传统的关系型数据库面临性能瓶颈。而Redis作为一种高性能的非关系型数据库,逐渐成为高并发场景...
    99+
    2023-11-07
    解决方案 数据存储 高并发
  • 怎样解决Mysql乱码的问题
    本篇内容主要讲解“怎样解决Mysql乱码的问题”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎样解决Mysql乱码的问题”吧! 系统是Fedora15,通过s...
    99+
    2024-04-02
  • Laravel Homestead安装的问题及解决方法是怎样的
    今天就跟大家聊聊有关Laravel Homestead安装的问题及解决方法是怎样的,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Laravel 致力于让整个 PHP 开发体验变得更愉...
    99+
    2023-06-21
  • ASP 中常见的并发问题及解决方案
    ASP 中常见的并发问题及解决方案 在 ASP 应用程序中,当多个用户同时访问同一个资源时,会出现并发问题。这些问题会导致应用程序崩溃、数据损坏或数据不一致等严重后果。因此,ASP 开发人员需要了解并发问题的原因和解决方案。 一、并发问题的...
    99+
    2023-11-12
    并发 数据类型 编程算法
  • HTML5中SVG对决canvas及长处和适用场景是怎样的
    这篇文章给大家介绍HTML5中SVG对决canvas及长处和适用场景是怎样的,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。到目前为止,SVG与Canvas的主要特性均已经总结完毕了。它...
    99+
    2024-04-02
  • JS在IE和Firefox兼容性问题及解决方法是怎样的
    JS在IE和Firefox兼容性问题及解决方法是怎样的,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。你对JS在IE和Firef...
    99+
    2024-04-02
  • Redis中秒杀场景下超时与超卖问题的解决方案
    目录超时1.redis连接超时原因2.解决方法超卖1.秒杀超卖现象2.解决方案(1)利用乐观锁淘汰用户,解决超卖问题(2)、使用reids的 watch + multi + setn...
    99+
    2024-04-02
  • mysql在windows中安装问题是怎样的
    这期内容当中小编将会给大家带来有关mysql在windows中安装问题是怎样的,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。1、mysql 有两种安装包 .msi 和 z...
    99+
    2024-04-02
  • 分布式场景下的数组同步问题:Go语言的解决方案
    在分布式系统中,对于多个节点之间的数据同步问题,数组同步问题是一个常见的难点。特别是在高并发、大数据量的场景下,同步的效率和准确性更是考验着系统的稳定性。Go语言作为一门高效且简洁的编程语言,在处理分布式场景下的数组同步问题方面有着独特的...
    99+
    2023-10-09
    数组 分布式 同步
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作