详解MySQL的并发控制

这篇具有很好参考价值的文章主要介绍了详解MySQL的并发控制。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1.概述

2.事务

2.1.什么是事务

2.2.事务的隔离级别

2.2.1.三种数据一致性问题

2.2.2.四种隔离级别

2.3.如何设置隔离级别

3.锁

3.1.锁与事务的关系

3.2.分类

3.3.表锁

3.3.1.概述

3.3.2.读锁

3.3.3.写锁

3.3.4.保护机制

3.4.行锁

3.4.1.概述

3.4.2.什么是MVCC

3.4.3.mvcc的使用

3.4.4.间隙锁

3.4.5.行锁变表锁 


1.概述

所谓的并发控制,就是规避多个会话并发访问数据库带来的诸如脏数据之类的数据一致性问题,MySQL中提供了一系列的机制让我们可以去进行并发控制。

本质上来说MySQL就是用的两种锁来进行并发控制,一种是表锁,锁住整张表;一种是行锁,锁住某个数据行。

平时我们使用的时候,很少会直接去操作锁,因为MySQL已经帮我们封装的很好了,直接用innodb引擎+事务就能很好的进行并发控制,事务底层其实依赖的就是行锁。

本文会先聊事务、再聊表锁、行锁,但其实总的来说MySQL进行并发控制,就是行锁和表锁,事务的底层用的就是行锁,只是事务太重要了所以单独拎出来作为一个独立的章节聊。

2.事务

2.1.什么是事务

注意:只有innodb引擎是支持事务的,所以本文与事务相关的讨论,默认都是在innodb引擎下。

在实际使用中,会存在这样一类场景,我们希望几条SQL要么同时执行成功,要么同时失败,不能有的成功,有的失败。

比如网购下单,生成订单、扣减库存两条SQL,必须保证要么全部成功,要么全部失败,不能说生成订单成功,但是扣减库存失败了,或者说扣减库存成功但是生成订单失败了,以上任何一种情况都是会产生脏数据的。如果两者中有一者失败,另外一个也需要跟着执行不成功,从而保证数据的正确性。

事务就是为了满足将多条捆绑在一起,同成功,同失败而出现的。人们在实现事务过程中,发现事务要实现上面我们说的效果,那么就必须实现四点:

  • 原子性(Atomicity)
  • 一致性(Consistent)
  • 隔离性(Isolation)
  • 持久性(Durable)

也就是大名鼎鼎的ACID,很多地方称其为事务的四大特性。

1.原子性:

事务是一个原子操作单元,其对数据的修改,要么全部执行,要么全部不执行。

2.一致性:

数据库中的数据总是从一个状态到另一个状态,不能存在中间状态。继续以网购下单为例,一开始的数据库中的数据为A状态,执行完事务,扣减库存、新增订单后的数据状态为B状态,数据库只能由A到B,不能出现诸如扣了库存,没生成订单,或者生成了订单,没扣库存这样的中间状态。

3.隔离性:

一个事务在提交之前,其所做的修改对其它事务来说是不可见的。不保证隔离性会产生脏数据,这个很好理解,举个例子:

A的银行账户有400,有两个事务,彼此之间数据可见,也就是一个事务修改数据,不管提没提交其他事务都看得见。

事务1,A向B转200:

  • A的账户扣减200
  • B的账户新增200

事务2,A向C转200:

  • A的账户扣减200
  • C的账户新增200

如果在事务1中的1、2步的时间间隙内事务2间插执行完毕,那么在事务1第2步执行前A的账户中已经被扣减了两次200,余额为0,C的账户中多了200。

这时候如果在事务1的第2步中出错了、回滚,那么A的账户又会回到事务1第一步执行之前的状态,也就是A的账户又恢复成了400。最后C的账户平白无故多了200。

4.持久性:

事务完成后,其对数据的修改是永久的,即使系统断电、重启,也不会变。

2.2.事务的隔离级别

2.2.1.三种数据一致性问题

在没有隔离性的情况下,事物之间会出现3种数据一致性问题:

  1. 脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
  2. 不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。
  3. 幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。

2.2.2.四种隔离级别

隔离级别可理解为,隔离性的严格度,MySQL并不是固定死了各个事务间就是不可读的,而是规定了各种强度的隔离级别。

观察上面3种数据一致性问题就会发现,解决它们需要的隔离性是递增的,MySQL一共给出4种隔离级别,隔离性也是递增的,对应解决以上3个问题,有3种,加上1种3种问题都能覆盖解决的:

  1. Read Uncommitted(读未提交):最低的隔离级别,允许一个事务读取另一个事务尚未提交的数据变更。可能导致脏读(Dirty Read)问题。

  2. Read Committed(读已提交):确保一个事务只能读取另一个事务已经提交的数据变更。防止脏读问题,但可能导致不可重复读(Non-repeatable Read)问题。

  3. Repeatable Read(可重复读):确保在同一个事务中多次读取同一数据时,能够得到一致的结果。防止脏读和不可重复读问题,但可能导致幻读(Phantom Read)问题。

  4. Serializable(串行化):最高的隔离级别,强制事务串行执行,确保不会发生脏读、不可重复读和幻读问题。但是并发性能较差,通常不建议在高并发环境中使用。

2.3.如何设置隔离级别

可以在连接字符串中设置隔离级别:

jdbc:mysql://localhost/mydatabase?useSSL=false&characterEncoding=utf8&transactionIsolation=隔离级别

可以通过SQL在会话中设置隔离级别:

SET TRANSACTION ISOLATION LEVEL 隔离级别;

3.锁

3.1.锁与事务的关系

锁是计算机协调多个进程或线程并发访问某一资源的机制,用来解决并发访问带来的数据一致性问题。在数据库中,除传统的计算资源(如CPU、IO、RAM)的争用以外,数据更是会被并发访问的资源。所以MySQL数据库也用锁机制来保证数据并发访问的一致性。

不同的隔离级别底层就是用不同的锁来实现的。

3.2.分类

MySQL的锁可以从两种维度来分,

一个维度是按照锁的是一行,还是锁的是整张表,分为:

  • 行锁
  • 表锁

另一个维度是按照锁的操作是读操作,还是写操作,分为:

  • 读锁
  • 写锁

3.3.表锁

3.3.1.概述

MySQL中innodb引擎和myisam引擎均支持用lock tables指令来锁表。

3.3.2.读锁

读锁,一种共享锁,针对被锁表,所有会话都可以进行读操作,所有会话都无法进行写操作。加锁方和其他客户端的区别是,加锁方直接不允许进行写操作,而其他会话的写操作允许进行,只是会被阻塞挂起。锁解开后,所有挂起的操作线程会去重新争抢资源。

加锁指令:

lock tables 表名 read;

释放锁指令:

unlock tanles;

加锁方不允许进行写操作:

详解MySQL的并发控制

其它客户端的写操作在加锁方释放锁之前都被挂起:

详解MySQL的并发控制

3.3.3.写锁

写锁,排它锁,针对被锁表,加锁方可以读写,其他会话的写操作会直接失败,读操作会被阻塞挂起,解锁以后,被挂起的线程会重新去争抢资源。

加锁指令:

lock tables 表名 write;

其它会话的读操作、写操作在加锁方释放锁之前都被阻塞挂起:

详解MySQL的并发控制

 详解MySQL的并发控制

3.3.4.保护机制

读锁、写锁中,加锁方都只能读当前被自己锁定的表,这是MySQL的一个保护机制,为的就是强制要求加锁方给出一个说法,到底准备锁多久,不给说法不让走。

详解MySQL的并发控制

3.4.行锁

3.4.1.概述

innodb和myIsam最大的不同有两点,一是支持事务,二是支持行级锁。

3.4.2.什么是MVCC

行锁没有显式的声明办法,而是藏在默认实现中,MVCC 是 MySQL InnoDB 存储引擎的默认并发控制机制,其采用的就是表锁。

并发控制有几种处理方法,

第一种: 基于锁的并发控制,程序员B开始修改数据时,给这些数据加上锁,程序员A这时再读,就发现读取不了,处于等待情况,只能等B操作完才能读数据,这保证A不会读到一个不一致的数据,但是这个会影响程序的运行效率。

第二种:MVCC,每个用户连接数据库时,看到的都是某一特定时刻的数据库快照,在B的事务没有提交之前,A始终读到的是某一特定时刻的数据库快照,不会读到B事务中的数据修改情况,直到B事务提交,才会读取B的修改内容。

MVCC其实就是实现事务的关键,后续会有文章专门深入聊事务的实现,此处暂不展开。

3.4.3.mvcc的使用

首先有一个需要纠正的是,很多地方都说mvcc是通过手动提交来触发的,这是个误导,不管手动提交还是自动提交MVCC机制都是生效的,只是手动提交用来观察mvcc过程更加直观。

此处为了直观,我们也以手动提交为例,首先通过set  autocommit=0可以关闭自动提交。关闭后每次执行sql以后,通过commit命令来手动提交,才会对数据库产生影响,否则只会对当前操作方的数据快照有影响。innodb引擎中,其他客户端想查看到最新的数据情况也必须通过commit指令来做一次同步(因为innodb默认隔离级别为可重复读)。

当一个会话修改某行数据,未commit前,其他会话对该行数据的修改会阻塞挂起,直到先改那个会话commit为止。

详解MySQL的并发控制

3.4.4.间隙锁

使用范围条件匹配时,innodb会给符合条件的已有数据记录的索引加“范围锁”(范围锁是特殊的行锁),对于键值在条件范围内但并不存在的记录,叫做间隙(GAP),innodb也会对这个间隙加锁,这种机制叫做“间隙锁”。

详解MySQL的并发控制

3.4.5.行锁变表锁 

任何需要全表扫描的情况时,行锁都会升级为表锁。

因为MySQL不知道到底该锁哪行,所以会将整个表都锁起来,然后再进行全表扫描。

全表扫描的情况无非两种:

  1. 没建索引。
  2. 索引失效。

详解MySQL的并发控制文章来源地址https://www.toymoban.com/news/detail-446979.html

到了这里,关于详解MySQL的并发控制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 分布式系统概念和设计——(事务与并发控制)

    事务与并发控制 简介 事务的目标是在多个事务访问对象以及服务器面临崩溃的情况下,保证所有由服务器管理的对象始终维持在一个一致的状态上 事务是由客户定义的针对服务器对象的一组操作,组成为一个不可分割的单元,由服务器执行 服务器必须保证整个事务被执行,

    2024年02月07日
    浏览(45)
  • PostgreSQL 的事务管理和并发控制机制解析

    🌷🍁 博主 libin9iOak带您 Go to New World.✨🍁 🦄 个人主页——libin9iOak的博客🎐 🐳 《面试题大全》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 🌊 《IDEA开发秘籍》学会IDEA常用操作,工作效率翻倍~💐 🪁🍁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬

    2024年02月15日
    浏览(43)
  • 系统架构设计师---事务管理、并发控制、数据库的备份与恢复

    目录 事务管理       定义       事务的四个特性(ACID)     相关SQL语句 并发控制     并发操作     封锁  数据库的备份与恢复      备份(转储)与恢复        备份分类       数据库的四类故障          DBMS 运行的基本工作单位是事务,事务是用户定义的一个数据库

    2024年02月12日
    浏览(58)
  • 深入探讨MySQL并发事务的问题及解决方案

    人不走空                                                                          目录         🌈个人主页:人不走空       💖系列专栏:算法专题 ⏰诗词歌赋:斯是陋室,惟吾德馨 1. 脏读(Dirty Read) 2. 不可重复读(Non-repeatable Read) 3. 幻读(Phantom Rea

    2024年03月09日
    浏览(91)
  • MySQL高阶知识点(一)事务的并发问题和隔离级别

    简单来说,事务就是要保证一组数据库操作,要么全部成功,要么全部失败。 在 MySQL 中,事务支持是在 引擎层 实现的。 MySQL 是一个支持多引擎的系统,但并不是所有的引擎都支持事务。 如 MySQL 原生的 MyISAM 引擎就不支持事务,这也是 MyISAM 被 InnoDB 取代的重要原因之一。

    2024年02月12日
    浏览(33)
  • MySQL性能优化盲区(高并发情况下,事务内的数据先更新还是先查询?)

    近期看到了一个前阿里资深开发的学术分析视频: 高并发情况下,一个事务内有更新操作还有查询操作,那是先更新好,还是先无锁查询好? 仅70秒的视频,深感学问太深,但是海哥讲的有待补充,于是写下了这篇文章,作为补充。 鸣谢:前阿里资深开发极海Channel的技术分

    2024年03月15日
    浏览(50)
  • 【MySQL】事务是什么?事务的特性又是什么?

    事务是由一个或多个SQL语句构成的,在事务中,这些的SQL不可分割,是一个整体,整个事务类似于物理中的原子结构,不可再分。 简单概括,就是说,将多个语句给打包成一个 整体 了,在这个整体中的语句, 要么一条都不执行,要么全部执行 ,不存在部分执行或者部分不

    2024年04月08日
    浏览(41)
  • 掌控MySQL并发:深度解析锁机制与并发控制

    前一篇MySQL读取的记录和我想象的不一致——事物隔离级别和MVCC 讲了事务在并发执行时可能引发的一致性问题的各种现象。一般分为下面3种情况: 读 - 读情况:并发事务相继读取相同的记录。读取操作本身不会对记录有任何影响,不会引起什么问题,所以允许这种情况发生

    2024年02月04日
    浏览(39)
  • MySQL 多版本并发控制 MVCC

    事务的4个隔离级别以及对应的三种异常 读未提交( Read uncommitted ) 读已提交( Read committed ):脏读 可重复读( Repeatable read ):不可重复读 串行化( Serializable ):幻读 脏读:一个事务读取到了另外一个事务没有提交的数据; 不可重复读:在同一个事务中,两次读取同一

    2024年01月18日
    浏览(49)
  • MySQL多线程并发控制技巧分享

    在高并发的应用场景下,数据库的性能瓶颈往往出现在并发读写上。为了提高数据库的并发性能,我们需要对MySQL的多线程进行有效的并发控制。本文将分享一些MySQL多线程并发控制的技巧,帮助大家更好地理解和优化MySQL的并发性能。 调整线程缓存大小 MySQL中的线程缓存是一

    2024年02月06日
    浏览(98)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包