MySQL性能优化(三)事务与锁详解

news2024/10/6 0:28:10

文章目录

  • 什么是数据库事务?
    • 事务的四大特性:ACID
    • 事务的开启与结束
      • 案例表结构与数据
      • 案例
  • 事务并发的三大问题:
    • 脏读(一个事务读取到了其他事务未提交的数据)
    • 不可重复读(一个事务读取到其他事务已提交的数据造成读不一致)
    • 幻读(一个事务读取到了其他事务新增的数据造成读不一致)
  • 事务隔离级别 —— SQL92标准
    • 事务隔离级别的修改
    • 事务隔离级别的解决方案
      • 多版本并发控制(MVCC)核心思想
        • 案例
      • MVCC 实现原理:Read View(一致性视图)存储内容
        • ReadView判断规则
        • RC(已提交读)与RR(可重复读)中ReadView的区别
  • 锁🔒
    • MyIsam支持表锁,InnoDB支持行锁
      • 表锁与行锁的区别
      • 表锁的锁定与解锁
      • InnoDB锁类型(Lock Mode)
        • 共享锁:
        • 排他锁:
        • 意向锁:意向共享锁(IS) / 意向排他锁(IX)
    • 锁的作用:
    • InnoDB的行锁到底锁的是什么?锁住的是索引。
      • 案例
    • 行锁的算法:锁住什么范围?
      • 区间划分
      • 记录锁(Record Lock):锁定记录
      • 间隙锁(Gap Lock):锁定范围
      • 临键锁(Next-key Lock):锁定范围加记录
      • 事务隔离级别的实现:
  • 事务隔离级别的选择:RC(已提交读)和RR(可重复读)的主要区别
  • 死锁的条件
    • 开启标准监控和锁监控
    • 死锁的避免

  1. 事务的特性与事务并发造成的问题
  2. 事务读一致性问题的解决方案
  3. MVCC的原理
  4. 锁的分类,行锁的原理、行锁的算法
  5. 死锁的原因,如何避免

本文数据库版本:

select VERSION();
-- 5.7.41
show variables like '%engine%';
-- InnoDB
show global variables like '%tx_isolation%';
-- tx_isolation	REPEATABLE-READ  可重复读

什么是数据库事务?

事务是数据库管理系统执行过程的一个逻辑单元,由一个有限的数据库操作序列构成。并不是所有的存储引擎都支持事务。在MySQL中支持事务的存储引擎包括InnoDB和NDB。

事务的四大特性:ACID

  • Atomic:原子性(逻辑单位不可再分。要么全部成功,要么全部失败。InnoDB是通过undolog来实现的。)
  • Consistency:一致性(数据库完整性的约束没有破坏)
  • Isolation:隔离性(事务与其他事务之间相互隔离)
  • Durability:持久性(事务提交的结果是持久的。崩溃恢复crash-safe。redolog+双写缓冲。)

事务的开启与结束

案例表结构与数据

CREATE TABLE `student` (
  `id` int(16) NOT NULL AUTO_INCREMENT COMMENT '自增ID',
  `sno` varchar(16) DEFAULT NULL COMMENT '学号',
  `sname` varchar(64) DEFAULT NULL COMMENT '姓名',
  `company` varchar(128) DEFAULT NULL COMMENT '公司',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
INSERT INTO `student` (`id`, `sno`, `sname`, `company`) VALUES (1, '1001', 'Huathy', 'Huathy');
INSERT INTO `student` (`id`, `sno`, `sname`, `company`) VALUES (2, '1002', 'hx', 'Huathy');
INSERT INTO `student` (`id`, `sno`, `sname`, `company`) VALUES (3, '1003', 'Dy', 'Huathy');

案例

UPDATE student SET sname = 'WHX' where id = 2;
-- 增删改语句默认开启事务 autocommit	ON
show variables like '%autocommit%'
-- 开启事务;
begin;	
update student set sname = 'whx2' where id = 2;
-- 这里还没有提交,新开一个窗口则会查询出不同的结果。
select * from student where id = 2;
rollback;		-- 回滚事务,连接断开也会自动回滚
commit;			-- 提交事务
-- 一个事务持有的锁会在事务结束的时候释放

事务并发的三大问题:

事务并发的三大问题,其实都是数据库读一致性的问题。必须由数据库提供一定的事务隔离机制来解决。

脏读(一个事务读取到了其他事务未提交的数据)

image.png

不可重复读(一个事务读取到其他事务已提交的数据造成读不一致)

image.png

幻读(一个事务读取到了其他事务新增的数据造成读不一致)

image.png
区别:只有插入数据导致的前后两次读不一致,才称为幻读。

事务隔离级别 —— SQL92标准

隔离级别解决问题存在问题
Read UnCommitted(RU 未提交读)事务未提交的数据对其他事务也是可见的,会出现幻读。
Read Committed(RC 已提交读)解决脏读问题一个事务开启,只能看到已提交的事务所作的修改。
会出现不可重复读。
Repeatable Read(RR 可重复读)解决不可重复读问题在同一个事务中多次读取同样的数据结果是一样的。
这种未定义解决幻读问题。
Serializable(可序列化)解决所有问题最高的事务隔离级别,强行事务串行执行

image.png

事务隔离级别的修改

-- 设置事务隔离级别为 未提交读
set global transaction isolation level read uncommitted;
-- 设置事务隔离级别为 已提交读
set global transaction isolation level read committed;
-- 设置事务隔离级别为 可重复读
set global transaction isolation level repeatable read;
-- 设置事务隔离级别为 可序列化
set global transaction isolation level serializable;

事务隔离级别的解决方案

  1. 在数据读取前,对其加锁,阻止其他事务对数据进行修改(LBCC)。Lock Based Concurrency Control。
  2. 生成一个数据请求时间点的一致性数据快照(Snapshot),并利用这个快照来提供一定级别(语句级或事务级)的一致性读取(MVCC)。Multi Version Concurrency Control。

多版本并发控制(MVCC)核心思想

效果:建立一个快照,同一个事务,无论多少次查询的数据都是相同的。
规则:

  • 一个事务能看到的数据版本:
    1. 第一次查询之前已经提交的事务修改
    2. 本事务的修改
  • 一个事务不能看到的数据版本:
    1. 在本事务第一次查询之后创建的事务(事务ID比当前事务ID大)
    2. 活跃的(未提交的)事务的修改

案例

image.png

--  创建表
DROP TABLE IF EXISTS `mvcctest`;
CREATE TABLE `mvcctest`  (
  `id` int(11) NULL DEFAULT NULL,
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- 插入数据
truncate table mvcctest;
begin;
INSERT INTO `demo`.`mvcctest`(`id`, `name`) VALUES (1, 'whx');
INSERT INTO `demo`.`mvcctest`(`id`, `name`) VALUES (2, 'Huathy');
commit;

image.png

MVCC 实现原理:Read View(一致性视图)存储内容

image.png

ReadView判断规则

  1. 从数据的最早版本开始判断(undo log)
  2. 数据版本的trx_id = creator_trx_id,本事务修改,可以访问。
  3. 数据版本的trx_id < min_trx_id(未提交事务的最小ID),说明该版本在生成Read View前已经提交,可以访问。
  4. 数据版本的trx_id > max_trx_id(下一个事务ID),该版本是生成Read View后才开启的事务,不能访问。
  5. 数据版本的trx_id在min_trx_id和max_trx_id之间,看看是否在m_ids(活跃事务ID)中,如果在则不可以。如果不在则可以。
  6. 如果当前版本不可见,就找undo log链中的下一个版本。

RC(已提交读)与RR(可重复读)中ReadView的区别

RR的ReadView是事务第一次查询的时候就创建的。
RC的ReadView是事务每次查询的时候都会重新创建。

锁🔒

MyIsam支持表锁,InnoDB支持行锁

表锁与行锁的区别

锁粒度:表锁 > 行锁
加锁效率:表锁 > 行锁
冲突概率:表锁 > 行锁
并发性能:表锁 < 行锁

表锁的锁定与解锁

lock tables xxx read;
lock tables xxx write;;
unlock tables;

InnoDB锁类型(Lock Mode)

  • 共享锁(行锁):Shared Lock
  • 排他锁(行锁):Exclusive Lock
  • 意向共享锁(表锁):Intention Shared Lock
  • 意向排他锁(表锁):Intention Exclusive Lock

共享锁:

也成为读锁,S锁。共享锁就是多个事务对于同一个数据可以共享同一把锁。都能访问到数据,但是只读不能改。
加锁释锁方式:

select * from student where id = 1 lock in shared mode;
commit / rollback;

排他锁:

也成为写锁,X锁。排他锁不能与其他锁并存,如果一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的锁(共享锁、排他锁)。只有该获取了排他锁的事务是可以对数据行进行读写的。
加锁释锁方式:

-- 自动方式:
-- delete / update / insert 默认加上X锁
-- 手动方式:
select * from student where id=1 for update;
commit / rollback;

意向锁:意向共享锁(IS) / 意向排他锁(IX)

意向锁是由数据库引擎自己维护的,用户无法手动操作意向锁。

  1. 意向共享锁(Intention Shred Lock):表示事务准备给数据行加入共享锁,也就是说一个数据行加共享锁之前必须取得该表的IS锁。
  2. 意向排他锁(Intention Exclusive Lock):表示事务准备给数据行加入排他锁,说明事务在一个数据行加排他锁前必须先取得该表的IX锁。

问题:为什么需要(表级别的)意向锁?类似于一个锁标志。
一个事务能够成功给一张表加上表锁的前提是没有任何一个事务已经锁定了这个表的任意一行数据。

锁的作用:

为了解决并发资源竞争的问题。

InnoDB的行锁到底锁的是什么?锁住的是索引。

案例

  1. t1表:不使用索引,锁表
DROP TABLE IF EXISTS `t1`;
CREATE TABLE `t1` (
  `id` int(11) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `t1` (`id`, `name`) VALUES (1, '1');
INSERT INTO `t1` (`id`, `name`) VALUES (2, '2');
INSERT INTO `t1` (`id`, `name`) VALUES (3, '3');
INSERT INTO `t1` (`id`, `name`) VALUES (4, '4');

-- Session 1
begin;	
SELECT * FROM t1 WHERE id =1 FOR UPDATE;
  
-- Session 2
select * from t1 where id=3 for update;
INSERT INTO `t1` (`id`, `name`) VALUES (5, '5');

行锁锁住的是索引。但是t1表中没有建立主键索引,InnoDB使用了隐藏的_rowId。而我们这里的select语句并没有使用索引来访问,导致全表扫描。所以锁住了所有行。也就是锁表了。这也是我们加锁必须带上精确条件的原因。

  1. 使用主键索引t2
DROP TABLE IF EXISTS `t2`;
CREATE TABLE `t2` (
  `id` int(11) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `t2` (`id`, `name`) VALUES (1, '1');
INSERT INTO `t2` (`id`, `name`) VALUES (4, '4');
INSERT INTO `t2` (`id`, `name`) VALUES (7, '7');
INSERT INTO `t2` (`id`, `name`) VALUES (10, '10');
-- Session 1
begin;	
SELECT * FROM t2 WHERE id =1 FOR UPDATE;
-- Session 2
select * from t2 where id=1 for update;	
select * from t2 where id=4 for update;
ROLLBACK;
  1. 使用唯一索引t3
DROP TABLE IF EXISTS `t3`;
CREATE TABLE `t3` (
  `id` int(11) ,
  `name` varchar(255) ,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `t3` (`id`, `name`) VALUES (1, '1');
INSERT INTO `t3` (`id`, `name`) VALUES (4, '4');
INSERT INTO `t3` (`id`, `name`) VALUES (7, '7');
INSERT INTO `t3` (`id`, `name`) VALUES (10, '10');
-- Session 1
begin;
select * from t3 where name= '4' for update;
-- Session 2
select * from t3 where name = '4' for update;
select * from t3 where id = 4 for update;

select * from t3 where id = 1 for update;

image.png

行锁的算法:锁住什么范围?

区间划分

image.png

记录锁(Record Lock):锁定记录

image.png

间隙锁(Gap Lock):锁定范围

image.png
GapLock只在RR(可重复读)中存在。用来阻塞插入。解决幻读问题。

-- Session 1
begin;  
select * from t2 where name= '4' for update;
-- Session 2
INSERT INTO t2 VALUES (5, '5');
INSERT INTO t2 VALUES (6, '6');

临键锁(Next-key Lock):锁定范围加记录

Next-key Lock = GapLock + RecordLock
image.png

事务隔离级别的实现:

image.png

事务隔离级别的选择:RC(已提交读)和RR(可重复读)的主要区别

  1. RR的间隙锁会导致锁定范围的扩大
  2. 条件列未使用到索引,RR锁表,RC锁行
  3. RC的"半一致性"(semi-consistent)读可以增加update操作的并发性。

死锁的条件

互斥、不可剥夺、形成等待环路

开启标准监控和锁监控

# 开启标准监控和锁监控
set global innodb_status_output=on;
set global innodb_status_output_locks=on;
# 查看这条语句的加锁情况
show engine innodb status;

死锁的避免

  1. 顺序访问
  2. 数据排序
  3. 申请足够级别的锁
  4. 避免没有where条件(不命中索引)的操作
  5. 大事务分解成小事务
  6. 使用等值查询而不是范围查询

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/416473.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt在安卓手机输出‘hello,world‘

我也想实现这样的功能。 最开始的参考文章&#xff1a; (2条消息) Qt android 开发环境搭建_逝水流年丶轻染尘的博客-CSDN博客 方案1&#xff1a;(失败) 我之前已经下载过 Qt5.14.2了&#xff0c;所以我想直接添加组件 中间过程参考&#xff1a; (2条消息) Qt更新组件出现&…

敏捷开发模式下如何用 PingCode 这类工具迭代管理

迭代&#xff08;Sprint&#xff09;是 Scrum 敏捷开发框架的核心&#xff0c;正确的迭代可以帮助敏捷团队提高工作交付速度。Scrum 团队以完成迭代待办列表为工作目标&#xff0c;并在迭代结束时交付一定的产品增量。PingCode 以产品待办列表作为迭代管理的核心&#xff0c;因…

java并发编程之美第二章读书笔记

并发编程的其他基础知识 什么是多线程的并发编程 并发: 同一时间段内多个任务同时都在执行,且执行都没有执行结束,强调的是在一个时间段内同时执行,而一个时间段由多个时间积累而成的,所以并发的多个任务在单位时间内并不一定同时执行 并行: 单位时间内多个任务同时在执行…

基于GPT-4免费生成代码的工具!小游戏,管理系统都能生成!

Cursor支持Python、Java、C、JavaScript、C#等等&#xff0c;可AI生成代码&#xff0c;功能非常强大&#xff01;这篇教程将教你如何下载安装&#xff0c;带你玩转Cursor 目录 话不多说&#xff0c;先看能力&#xff1a; 只需要三步&#xff0c;就可以AI出你想要的代码&#x…

测试基础知识

开发模型和测试模型 软件的生命周期 软件的生命周期指的是产品从设想开始到软件不再使用的时间。 软件的生命周期可以分为6个阶段&#xff1a;需求分析&#xff0c;计划&#xff0c;设计&#xff0c;编码&#xff0c;测试&#xff0c;运行维护。 瀑布模型 适用项目&#xf…

[考研数据结构]第3章之栈的基本知识与操作

文章目录 栈的基本概念 栈的实现 顺序栈 共享栈 链栈 栈的基本概念 栈的定义 栈&#xff08;Stack&#xff09;是只允许在一端进行插入或删除操作的线性表 相关术语 栈顶&#xff08;Top&#xff09;线性表允许进行插入或删除的那一端称之为栈顶栈底&#xff08;Bottom&…

JAVASE基础(二)

这里写目录标题JAVASE基础11.科学计数法12.编码和字符集12.编译格式问题13.类型转换类型级别自动类型转换强制类型转换特殊情况14.final修饰符a.修饰变量b.修饰方法c.修饰类15.scanner使用16.两个数交换引入中间变量位运算数学数方法一数学计数方法二17.扩展赋值运算符&#xf…

递归算法_字符串反转_20230412

递归算法-字符串反转 前言 递归算法对解决重复的子问题非常有效&#xff0c;字符串反转也可以用递归算法加以解决&#xff0c;递归算法设计的关键是建立子问题和原问题之间的相关性&#xff0c;同时需要确立递归退出的条件&#xff1b;如果递归退出的条件无法确定&#xff0c…

【LeetCode: 面试题 17.13. 恢复空格 | 暴力递归=>记忆化搜索=>动态规划】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

Redis安装和配置

目录本章重点Redis安装Redis启动和停止配置后台启动连接前的配置本章重点 主要掌握安装和启动了解redis的配置文件进行配置掌握Redis几种启动方式 Redis安装 下载 Redis官网 点击下载 解压 然后将下载好的压缩包上传到服务器,进行解压! tar zxvf 进行解压 编译 我们要进行编…

4.12每日一练

题目&#xff1a;给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。你可以假设除了数字 0 之外&#xff0c;这两个数…

学生信息管理系统【GUI/Swing+MySQL】(Java课设)

系统类型 Swing窗口类型Mysql数据库存储数据 使用范围 适合作为Java课设&#xff01;&#xff01;&#xff01; 部署环境 jdk1.8Mysql8.0Idea或eclipsejdbc 运行效果 本系统源码地址&#xff1a;https://download.csdn.net/download/qq_50954361/87673902 更多系统资源库…

安全运营场景下的机器学习算法应用

观测到一个有意思的现象&#xff1a; 假设把安全划分为 基础安全 和 业务安全&#xff0c;PR类的议题中&#xff0c;会出现分级&#xff1a;基础安全领域&#xff0c;喜欢讲纵深防御&#xff0c;给出一个炫酷的架构图&#xff0c;然后各种技术关键字往上标&#xff1b;业务安全…

Doris集群的安装部署

目录 安装与部署 软硬件配置​ 1、机器选择 2、软件选择 3、环境信息修改和部署架构 4、安装部署Doris 5、启动FE 6、在FE节点启动MySQL客户端 7、在BE节点启动be 8、查看BE状态 8、查看FE状态是否正常 WEBUI 官方建议 安装与部署 该文档主要介绍了部署 Doris 所…

如何压缩Outlook数据文件大小

由于 Outlook 需要管理大量的电子邮件&#xff0c;Outlook 偶尔会出现问题是很正常的。 但是&#xff0c;如果你注意到 Outlook 打开或加载的时间过长&#xff0c;这可能是一个严重的问题。此外&#xff0c;你还可能面临其他问题&#xff0c;比如收件箱加载时间过长&#xff0…

WebWorker、ThreeJs的渲染和控制

在 ios16.4 版本中已经开始支持了 OffscreenCanvas &#xff0c;那看样子&#xff0c;是时候再把Three做一波优化了 背景介绍 在之前的项目经验中&#xff0c;如果使用threejs加载比较大的3d场景&#xff0c;那么在创建 threejs 的对象和绘制的时候&#xff0c;会占用浏览器线…

认识C++《共、枚、指1》

目录 前言: 1.共用体的基本知识 2.匿名共用体 3.枚举 3.1设置枚举值 3.2枚举的应用场景 3.3枚举变量的取值范围 4.地址和自由存储空间 5.指针的思想 6.指针的声明和初始化 前言: 指针内容比较多&#xff0c;还需要再出一篇。久等了&#xff01;&#xff01;我看了我的…

数据库中的视图及三级模式结构

文章目录一、视图二、数据库三级模式结构一、视图 简单地说&#xff0c;视图可以看成是一个窗口&#xff0c;它所反映的是一个表或若干表的局部数据&#xff0c;可以简化查询语句。视图一经定义&#xff0c;用户就可以把它当作表一样来查询数据。 但视图和基本表不同&#xf…

Python算法设计 - Karatsuba乘法

版权声明&#xff1a;原创不易&#xff0c;本文禁止抄袭、转载&#xff0c;侵权必究&#xff01; 目录一、Karatsuba 乘法二、算法思路三、Python算法实现四、作者Info一、Karatsuba 乘法 当你在纸上做两个数字的乘法时&#xff0c;一般我们都是用小时候学到的方法&#xff1a…

22.SSM-JdbcTemplate总结

目录 一、JdbcTemplate对象。 &#xff08;1&#xff09;Spring产生JdbcTemplate对象。 &#xff08;2&#xff09;JdbcTemplate常用操作。 &#xff08;3&#xff09;知识要点。 一、JdbcTemplate对象。 &#xff08;1&#xff09;Spring产生JdbcTemplate对象。 这个是Sp…