当前位置: 首页 > news >正文

MYSQL事务原理分析

目录

  • 事务是什么
  • ACID特性
    • 原子性(A)
    • 隔离性(I)
    • 持久性(D)
    • 一致性(C)
  • 隔离级别
    • 简介
    • 有些什么
      • READ UNCOMMITTED(读未提交)
      • READ COMMITTED(读已提交)
      • REPEATABLE READ(可重复读)
      • SERIALIZABLE
    • 实现
      • MVCC
      • 锁类型
      • 锁算法
  • 修改事务隔离性
  • 并发异常
    • 读异常
      • 脏读
      • 不可重复读
      • 幻读
      • 丢失更新
        • 回滚覆盖
        • 提交覆盖
    • 并发死锁
      • 原因
      • 查看死锁
        • 系统表
        • 开启日志
        • 线上查看
        • 如何避免死锁

事务是什么

  1. 将数据库从一种一致性状态转换为另一种一致性状态
  2. 可以是一条语句,也可以是一组语句

ACID特性

原子性(A)

  1. 事务操作要么都做(提交),要么都不做(回滚)
  2. 事务是访问并更新数据库各种数据项的一个程序执行单元,是不可分割的工作单位
  3. 通过 undolog 来实现回滚操作。undolog 是将事务每步具体操作记录在共享表中,当回滚时,回放事务具体操作的逆运算

隔离性(I)

  1. 事务的隔离性要求每个读写事务的对象对其他事务的操作对象能相互分离,并发事务之间不会相互影响,设定了不同程度的隔离级别,通过适度破环一致性,得以提高性能
  2. 通过 MVCC 和 锁来实现
  3. 数据库中提供粒度锁的策略,针对表(聚集索引B+树)、页(聚集索引B+树叶子节点)、行(叶子节点当中某一段记录行)三种粒度加锁

持久性(D)

  1. 事务提交后,事务DML操作将会持久化(写入 redolog 磁盘文件 哪一个页 页偏移值 具体数据)
  2. 即使发生宕机等故障,数据库也能将数据恢复。redolog 记录的是物理日志

一致性(C)

  1. 一致性指事务将数据库从一种一致性状态转变为下一种一致性的状态,在事务执行前后,数据库完整性约束不会被破坏
  2. 一个事务单元需要提交之后才会被其他事务可见。例如:一个表的姓名是唯一键,如果一个事务对姓名进行修改,但是在事务提交或事务回滚后,表中的姓名变得不唯一了,这样就破坏了一致性
  3. 一致性由原子性、隔离性以及持久性共同来维护的

隔离级别

简介

  1. ISO 和 ANIS SQL 标准制定了四种事务隔离级别的标准,各数据库厂商在正确性和性能之间做了妥协,并没有严格遵循这些标准;
  2. MySQL innodb默认支持的隔离级别是 REPEATABLE READ

有些什么

READ UNCOMMITTED(读未提交)

  1. 该级别下读不加锁,
  2. 写加排他锁
  3. 写锁在事务提交或回滚后释放锁

READ COMMITTED(读已提交)

  1. 从该级别后支持 MVCC ,也就是提供一致性非锁定读
  2. 此时读取操作读取历史快照数据
  3. 该隔离级别下读取历史版本的最新数据,所以读取的是已提交的数据

REPEATABLE READ(可重复读)

  1. 支持MVCC
  2. 此时读取操作读取事务开始时的版本数据

SERIALIZABLE

实现

MVCC

  1. 多版本并发控制,
  2. 读取过程中,遇到其他进、线程对该资源加写锁(X锁,又称行写锁、排他锁),则读取该资源的快照(以前存储的数据)。

  1. 用来处理并发 DML 操作

锁类型

  1. 表锁
  2. 页锁
  3. 行锁(记录锁)
  4. 共享锁(S锁)
    在 SERIALIZABLE 隔离级别下,默认帮读操作加共享锁
    在 REPEATABLE READ 隔离级别下,需手动加共享锁,可解决幻读问题
    在 READ COMMITTED 隔离级别下,没必要加共享锁,采用的是 MVCC
    在 READ UNCOMMITTED 隔离级别下,既没有加锁也没有使用 MVCC
    手动加S锁:
select * from xxx lock in share mode;
  1. 排他锁 (X锁)
    事务删除或更新加的锁;对某一行加锁
    插入的时候,会在中间再加一个插入意向锁
    在4种隔离级别下,都添加了排他锁,事务提交或事务回滚后释放锁
    手动加X锁:
select * from xxx for update;
  1. 意向共享锁(IS)
    仅仅为了告知即将操作的事务:当前有事务进正在进行访问,且其中几行已经加入共享锁
  2. 意向排他锁(IX)
    仅仅为了告知即将操作的事务:当前有事务进正在进行访问,且其中几行已经加入排他锁
  3. 意向锁
    该表中存在锁,表明该锁正在接受某事务访问
    目的:排除表层次的锁操作
  4. AUTO-INC Lock (AI锁)
    自增锁,是一种特殊的表级锁,发生在 AUTO_INCREMENT 约束下的插入操作。
    采用的一种特殊的表锁机制。
    完成对自增长值插入的SQL语句后立即释放。
    在大数据量的插入会影响插入性能,因为另一个事务中的插入会被阻塞。
    从MySQL 5.1.22开始提供一种轻量级互斥量的自增长实现机制,该机制提高了自增长值插入的性能。
    较低概率造成B+树的分裂。
  5. 锁的兼容性
    在这里插入图片描述
    注:其中IS、IX与S、X的冲突是当X、S为全表操作时候会产生冲突,单行操作并不会产生冲突
    意向锁不会与行锁冲突!!!

锁算法

  1. Record Lock
    单个行记录上的锁

  2. Gap Lock
    间隙锁,锁定一个范围,但不包含记录本身, 全开区间
    解决幻读问题
    REPEATABLE READ级别支持间隙锁
    产生死锁重要原因之一

  3. Next-Key Lock (记录锁+间隙锁)
    产生死锁重要原因之一
    锁定一个范围,并且锁住记录本身,左开右闭区间
    REPEATABLE READ级别支持间隙锁

  4. Insert Intention Lock (插入意向锁)
    插入意向锁,insert操作的时候产生。
    在多事务同时写入不同数据至同一索引间隙的时候,并不需要等待其他事务完成,不会发生锁等待。
    提升插入的并发性能。
    假设有一个记录索引包含键值4和7,两个不同的事务分别插入5和6,每个事务都会产生一个加在4-7之间的插入意向锁,获取在插入行上的排它锁,但是不会被互相锁住,因为数据行并不冲突。
    产生死锁重要原因之一

  5. AUTO-INC Lock (AI锁)
    比行插入方式,较低概率造成B+数的分裂,所以它的性能更高

  6. 锁兼容
    在这里插入图片描述
    如果有事务已经持有insert Intention key, 这个时候不会影响其他事务
    如果有事务想要执行insert Intention key 但是这个时候已经有事务持有了GAP或者NEXT-KEY, 则会产生阻塞

修改事务隔离性

# set transaction isolation level read uncommitted;
# set transaction isolation level read committed;
# set transaction isolation level repeatable read;
set transaction isolation level SERIALIZABLE;
begin
select * from table;
update table_a set name='lsy';
delete from table_b;
commit

并发异常

读异常

在这里插入图片描述

  1. 一个事务已经获取了插入意向锁,对其他事务是没有任何影响的
  2. 一个事务想要获取插入意向锁,如果有其他事务已经加了 gap lock 或 Next-key lock 则会阻塞

脏读

事务A可以读到事务B未提交的数据

不可重复读

两次读取同一条记录,读到了不一样的结果,因为有其他事务对该数据做了修改

幻读

两次读取同一范围内的记录,结果的集合不一样
由于repeatable read中规定:读取事务开始前前的版本行数据,那么在该隔离级别下,不管该事务中对改行数据做什么操作,该数据都将不变

丢失更新

回滚覆盖

该问题已经被数据库修复,数据库将拒绝该操作,
该问题会将数据回滚为事务开始之前的数据
比如事务a读取数据后做了回滚,在这期间,事务B对该数据做了修改,结果事务a回滚时候将使得事务B的操作无效

提交覆盖

两个事务同时写一个数据,后提交的事务覆盖掉了先提交的数据

并发死锁

使用 wait-for graph的方式进行死锁检测
异常报错:deadlock found when trying to get lock

原因

  1. 相反方向加锁
  2. 隔离级别冲突

查看死锁

系统表

-- 开启标准监控
CREATE TABLE innodb_monitor (a INT) ENGINE=INNODB;
-- 关闭标准监控
DROP TABLE innodb_monitor;
-- 开启锁监控
CREATE TABLE innodb_lock_monitor (a INT) ENGINE=INNODB;
-- 关闭锁监控
DROP TABLE innodb_lock_monitor

开启日志

-- 开启标准监控
set GLOBAL innodb_status_output=ON;
-- 关闭标准监控
set GLOBAL innodb_status_output=OFF;
-- 开启锁监控
set GLOBAL innodb_status_output_locks=ON;
-- 关闭锁监控
set GLOBAL innodb_status_output_locks=OFF;
-- 将死锁信息记录在错误日志中
set GLOBAL innodb_print_all_deadlocks=ON;

线上查看

-- 查看事务
select * from information_schema.INNODB_TRX;
-- 查看锁
select * from information_schema.INNODB_LOCKS;
-- 查看锁等待
select * from information_schema.INNODB_LOCK_WAITS;

如何避免死锁

  1. 尽可能以相同顺序来访问索引记录和表;
  2. 如果能确定幻读和不可重复读对应用影响不大,考虑将隔离级别降低为RC;
  3. 添加合理的索引,不走索引将会为每一行记录加锁,死锁概率非常大;
  4. 尽量在一个事务中锁定所需要的所有资源,减小死锁概率;
  5. 避免大事务,将大事务分拆成多个小事务;大事务占用资源多,耗时长,冲突概率变高;
  6. 避免同一时间点运行多个对同一表进行读写的概率;

相关文章:

  • ORB-SLAM3算法学习—Frame构造—基于SAD滑窗的双目特征匹配
  • 【最佳实践】gorm 联表查询 joins
  • http请求走私漏洞原理,利用,检测,防护
  • simulink中比scope模块还好用的平替出图工具?
  • 微信小程序和H5之间互相跳转、互相传值
  • web前端期末大作业 html+css家乡旅游主题网页设计 湖北武汉家乡介绍网页设计实例
  • PS-HDR图像编辑与应用
  • 2022亚太杯C题思路代码分析
  • 涨知识!Python 的异常信息还能这样展现
  • JDBC编程
  • HTML+CSS期末大作业 中国传统美食网站设计 节日美食13页 html5网页设计作业代码 html制作网页案例代码 html大作业网页代码
  • 基于Java+Spring+Vue+elementUI大学生求职招聘系统详细设计实现
  • matlab在管理学中的应用简matlab基础【二】
  • 【安装Ubuntu18.04遇到的问题】未找到WIFI适配器
  • 发明专利与实用新型专利的不同
  • “寒冬”下的金三银四跳槽季来了,帮你客观分析一下局面
  • 【140天】尚学堂高淇Java300集视频精华笔记(86-87)
  • 【347天】每日项目总结系列085(2018.01.18)
  • 【刷算法】求1+2+3+...+n
  • Hexo+码云+git快速搭建免费的静态Blog
  • HTTP请求重发
  • Java,console输出实时的转向GUI textbox
  • java取消线程实例
  • JS基础篇--通过JS生成由字母与数字组合的随机字符串
  • Netty+SpringBoot+FastDFS+Html5实现聊天App(六)
  • PAT A1120
  • PHP的类修饰符与访问修饰符
  • Rancher-k8s加速安装文档
  • REST架构的思考
  • Travix是如何部署应用程序到Kubernetes上的
  • Vue.js源码(2):初探List Rendering
  • 代理模式
  • 高程读书笔记 第六章 面向对象程序设计
  • 海量大数据大屏分析展示一步到位:DataWorks数据服务+MaxCompute Lightning对接DataV最佳实践...
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 基于Mobx的多页面小程序的全局共享状态管理实践
  • 排序算法学习笔记
  • 浅谈Golang中select的用法
  • 为什么要用IPython/Jupyter?
  • 验证码识别技术——15分钟带你突破各种复杂不定长验证码
  • 3月7日云栖精选夜读 | RSA 2019安全大会:企业资产管理成行业新风向标,云上安全占绝对优势 ...
  • 新年再起“裁员潮”,“钢铁侠”马斯克要一举裁掉SpaceX 600余名员工 ...
  • ​Python 3 新特性:类型注解
  • ​中南建设2022年半年报“韧”字当头,经营性现金流持续为正​
  • # 执行时间 统计mysql_一文说尽 MySQL 优化原理
  • #常见电池型号介绍 常见电池尺寸是多少【详解】
  • ${ }的特别功能
  • (4)STL算法之比较
  • (附源码)springboot码头作业管理系统 毕业设计 341654
  • (一)RocketMQ初步认识
  • (转)淘淘商城系列——使用Spring来管理Redis单机版和集群版
  • (转载)在C#用WM_COPYDATA消息来实现两个进程之间传递数据
  • **Java有哪些悲观锁的实现_乐观锁、悲观锁、Redis分布式锁和Zookeeper分布式锁的实现以及流程原理...
  • .bat批处理(一):@echo off
  • .NET C#版本和.NET版本以及VS版本的对应关系