Mysql事务原理

news2024/11/18 17:47:42

脑图

一、概述

事务:一组操作要么全部成功,要么全部失败,目的是为了保证数据最终的一致性。
数据库一般都会并发执行多个事务,多个事务可能会并发的对相同的一批数据进行增删改查操作,可能就会导致我们说的脏写、脏读、不可重复读、幻读这些问题。
这些问题的本质都是数据库的多事务并发问题,为了解决多事务并发问题,数据库设计了事务隔离机制、锁机制、MVCC多版本并发控制隔离机制、日志机制,用一整套机制来解决多事务并发问题

二、ACID

事务具有以下4个属性,通常简称为事务的ACID属性。
● 原子性(Atomicity) :当前事务的操作要么同时成功,要么同时失败。原子性由undo log日志来实现。
● 一致性(Consistent) :使用事务的最终目的,由其它3个特性以及业务代码正确逻辑来实现。
● 隔离性(Isolation) :在事务并发执行时,他们内部的操作不能互相干扰。隔离性由MySQL的各种锁以及MVCC机制来实现。
● 持久性(Durable) :一旦提交了事务,它对数据库的改变就应该是永久性的。持久性由redo log日志来实现

三、并发事务处理带来的问题

更新丢失(Lost Update)或脏写当两个或多个事务选择同一行数据修改,有可能发生更新丢失问题,即最后的更新覆盖了由其他事务所做的更新
脏读(Dirty Reads)事务A读取到了事务B已经修改但尚未提交的数据
不可重读(Non-Repeatable Reads)事务A内部的相同查询语句在不同时刻读出的结果不一致
幻读(Phantom Reads)事务A读取到了事务B提交的新增数据

四、事务隔离级别

脏读、不可重复读和幻读,都是数据库读一致性问题,必须由数据库提供一定的事务隔离机制来解决。

隔离级别脏读(Dirty Read)不可重复读(NonRepeatable Read)幻读(Phantom Read)
读未提交(Read uncommitted)可能可能可能
读已提交(Read committed)不可能可能可能
可重复读(Repeatableread)不可能不可能可能
可串行化(Serializable)不可能不可能可能不可能

数据库的事务隔离越严格,并发副作用越小,但付出的代价也就越大,因为事务隔离实质上就是使事务在一定程度上“串行化”进行,这显然与“并发”是矛盾的。
不同的应用对读一致性和事务隔离程度的要求也是不同的,比如许多应用对“不可重复读"和“幻读”并不敏感,可能更关心数据并发访问的能力。
查看当前数据库的事务隔离级别: show variables like ‘tx_isolation’;
设置事务隔离级别:set tx_isolation=‘REPEATABLE-READ’;
Mysql默认的事务隔离级别是可重复读(Oracle默认事务为读已提交),用Spring开发程序时,如果不设置隔离级别默认用Mysql设置的隔离级别,如果Spring设置了就用已经设置的隔离级别。

查看和设置mysql事务隔离级别

--当前会话隔离级别
select @@transaction_isolation;
--系统隔离级别
select @@global.transaction_isolation;
--MySQL 5.7.20前可以使用
set tx_isolation='read-uncommitted';
--MySQL 5.7.20后弃用tx_isolation
set session transaction isolation level read uncommitted;--设置读未提交
set session transaction isolation level read committed;--设置读已提交
set session transaction isolation level  repeatable read;--设置可重复读
set session transaction isolation level Serializable;--可串行化

事务隔离级别案例分析

表结构与数据

CREATE TABLE `account`(
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`balance` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `account` (`name`, `balance`) VALUES ('lilei', '450');
INSERT INTO `account` (`name`, `balance`) VALUES ('hanmei', '16000');
INSERT INTO `account` (`name`, `balance`) VALUES ('lucy', '2400');

读未提交(Read uncommitted)

打开两个窗口设置隔离级别为 读未提交(Read uncommitted)

select @@transaction_isolation;
set session transaction isolation level read uncommitted;
select  * from account;
update account a set a.balance=500 where a.id='1';

在这里插入图片描述

select @@transaction_isolation;
set session transaction isolation level read uncommitted;
select  * from account;

在这里插入图片描述
读未提交存在问题:
一旦客户端console_1的事务因为某种原因回滚,所有的操作都将会被撤销,那客户端console_2查询到的数据其实就是脏数据
注意:如果事务1修改lilei金额为500时候,没有提交事务。事务2这个时候去做查询,查询到金额为500,想要做增加50的业务逻辑,请使用

--请使用
update account a set a.balance=a.balance+50 where a.id='1';
--不能用
update account a set a.balance=550 where a.id='1';

这个操作来完成,如果直接设置balance为550,一旦事务1回滚必定造成脏数据,因为同时对id为1的数据进行修改是会加写锁的,使用balance+50情况下事务1回滚,这里的banlance就是450而不是500了。

读已提交(Read committed)

打开两个窗口设置隔离级别为 读已提交(Read committed)

select @@transaction_isolation;
set  session transaction isolation level read committed;
select  * from account;
update account a set a.balance=500 where a.id='1';

在这里插入图片描述

select @@transaction_isolation;
set  session transaction isolation level read committed;
--事务1未提交 450
select  * from account;
--事务1提交了 500
select  * from account;

在这里插入图片描述
读已提交存在问题:
在这里插入图片描述
同一个事务下面两次查询到的值不同,即产生了不可重复读的问题。

可重复读(Repeatableread)

可重复读隔离级别在事务开启的时候,第一次查询是查的数据库里已提交的最新数据,这时候全数据库会有一个快照(当然数据库并不是真正的生成了一个快照),在这个事务之后执行的查询操作都是查快照里的数据,别的事务不管怎么修改数据对当前这个事务的查询都没有影响,但是当前事务如果修改了某条数据,那当前事务之后查这条修改的数据就是被修改之后的值,但是查其它数据依然是从快照里查,不受影响。
打开两个窗口设置隔离级别为 可重复读(repeatable read)

set  session transaction isolation level repeatable read;
select @@transaction_isolation;
select  * from account;
update account a set a.balance=500 where a.id='1';

在这里插入图片描述

set  session transaction isolation level repeatable read;
select @@transaction_isolation;
--事务1未提交 450
select  * from account;
--事务1提交了 450 提交后真实为500
select  * from account;

在这里插入图片描述
这时候如果在事务2这里,进行lilie的balance+50,结果是550而不是500

update account a set a.balance=balance+50 where a.id='1';

在这里插入图片描述
可重复读的隔离级别下使用了MVCC(multi-version concurrency control)机制,select操作是快照读(历史版本);insert、update和delete是当前读(当前版本)

insert into account(name, balance) value ('zk',1000);

在这里插入图片描述

select @@transaction_isolation;
set  session transaction isolation level repeatable read;
#事务1未提交 插入一条数据
select  * from account;
#事务1提交了 还是未查询到新增数据
select  * from account;
update account a set a.balance=balance+50 where a.id=4;
select  * from account;

在这里插入图片描述
在这里插入图片描述

可串行化(Serializable)

打开两个窗口设置隔离级别为 串行化

select @@transaction_isolation;
set  session transaction isolation level serializable;
select  * from account a where a.id=1;

在这里插入图片描述

select @@transaction_isolation;
set  session transaction isolation level serializable;
--事务1未提交
update account a set a.balance=balance+50 where a.id=1;

在这里插入图片描述
说明在串行模式下innodb的查询也会被加上行锁,如果查询的记录不存在会给这条不存在的记录加上锁(这种是间隙锁)。
如果客户端1执行的是一个范围查询,那么该范围内的所有行包括每行记录所在的间隙区间范围都会被加锁。此时如果客户端2在该范围内插入数据都会被阻塞,所以就避免了幻读。
这种隔离级别并发性极低,开发中很少会用。

事务问题定位

--查询执行时间超过1秒的事务
SELECT
*
FROM
information_schema.innodb_trx
WHERE
TIME_TO_SEC( timediff( now( ), trx_started ) ) > 1;
--强制结束事务
--kill 事务对应的线程id(就是上面语句查出结果里的trx_mysql_thread_id字段的值)

在这里插入图片描述

五、大事务的影响

● 并发情况下,数据库连接池容易被撑爆
● 锁定太多的数据,造成大量的阻塞和锁超时
● 执行时间长,容易造成主从延迟
● 回滚所需要的时间比较长
● undo log膨胀
● 容易导致死锁

六、事务优化

● 将查询等数据准备操作放到事务外
● 事务中避免远程调用,远程调用要设置超时,防止事务等待时间太久
● 事务中避免一次性处理太多数据,可以拆分成多个事务分次处理
● 更新等涉及加锁的操作尽可能放在事务靠后的位置
● 能异步处理的尽量异步处理
● 应用侧(业务代码)保证数据一致性,非事务执行

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

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

相关文章

水站桶装水订水系统桶装水小程序,改变了桶装水行业传统的送水模式;

水站桶装水订水系统桶装水小程序,改变了桶装水行业传统的送水模式,客户通过线上下单,送水工实时接单配送,空桶更好的记录管理,财务数据在后台清晰明了,提高了水站的工作效率。 除此之外,还有很多…

网络系统集成实验(五)| 系统集成路由器OSPF动态、综合路由配置

一、前言 该系列文章将会对网络系统集成课程中相关实验进行更新,本篇为第五篇,有关路由器的OSPF、综合路由配置,包括了OSPF的配置实验、单臂路由实验、RIP配置实验、综合实验等。 注意:该实验的后半部分综合实验基于前面的实验&am…

java Collection集合使用笔记

1、Collection集合概述 它是单例集合的最顶层接口,它表示一组对象,这些对象也称之为Collection的元素JDK不提供此接口任何直接实现,但提供更具体的子接口(如:List和Set)实现创建Collection集合对象的方法&…

麒麟信安与飞腾携手共赴云端

当前各行业已进入全面云化时代,云桌面技术作为典型办公终端替代方案,凭借其数据安全、便捷运维、综合成本占优的优势正逐步在各行业应用实施。伴随十四五规划加速数字化转型及信息产业核心技术自主化发展,各政企组织迫切需要基于国产软硬件实…

gmap构建离线地图,用createCustomerTiledLayer方法,瓦片地址尾部多了 ?x={x}y={y}z{z} 导致无法显示地图。

gmap构建离线地图,用createCustomerTiledLayer方法,瓦片地址尾部多了 ?x{x}&y{y}&z&{z} 导致无法显示地图。 function initMap() {this.map new GL.Map(map, {center: "120.650847,31.3092434",zoom: 12,zoomControl: false,sca…

青大数据结构【2018】【算法设计】

关键词: 单链表递增、树的先序遍历 1)带头结点的单链表L,从首结点开始,依次两两比较,如果前者大于等于后者,说明是非递增的;否则递增。 2) 1)先遍历二叉树,…

【mars3d】基于vue3的marsgis通用UI库 mars-ui 的使用

一名脑残程序员的mars-ui心酸使用记录。 通过mars3d的官网我们可以看到,有配套的UI库使用,那么我们如何使用到自己的项目中呢,跟着文章一步一步来吧! 1、引入UI库 ① 安装ant-design-vue cnpm install ant-design-vue --save②…

如何实现功能插件化

本文将介绍两种方式来实现功能插件化: Java SPISpring factories 在整个插件化的方案中,会涉及到如下 3 个组成部分: 插件定义(即将插件定义为一个接口) 插件实现(即对插件接口的实现) 这里…

【需求实现】输入多少就输出多少的拟合任务如何实现(二):进度条简化

文章目录 导读普通的输出方式上下求索TensorBoard是个不错的切入点与Callback参数对应的Callback方法官方的内置Callback官方进度条简单的猜测与简单的验证拼图凑齐了! 导读 在训练模型的过程中往往会有日志一堆一堆的困扰。我并不想知道,因为最后我会在…

今天给大家分享几款好用的卸载神器

在日常使用电脑的过程中,我们经常需要安装和卸载各种软件。然而,有时候使用操作系统自带的卸载程序可能无法完全清除程序及其相关文件和注册表项,导致系统出现垃圾文件和残留问题。为了解决这个困扰,今天我将向大家分享几款好用的…

【Spring】基于注解方式存取JavaBean:Spring有几种注入方式?有什么区别?

前言 Hello,我是小黄。众所周知,Spring是一个开源的Java应用程序框架,其中包括许多通过注解实现依赖注入的功能。Spring提供了多种注入方式,可以满足不同的需求和场景。常见的注入方式包括构造函数注入、Setter方法注入和属性注入…

【Redis】Redis的高可用与持久化

文章目录 一、Redis 高可用1. 概念2. 高可用技术以及作用2.1 持久化2.2 主从复制2.3 哨兵2.4 集群 二、Redis 持久化1. 持久化的功能2. Redis 持久化方式 三、RDB 持久化1. 概述2. 触发条件2.1 手动触发2.2 自动触发2.3 其他自动发机制 3. 执行流程4. 启动时加载 四、AOF 持久化…

Modin 入门学习

Modin 是一个 Python 第三方库,用于加速 Pandas 的 API 执行速度。原始的 Pandas 是单线程执行的,而 Modin 则重新打包了 Pandas 里面的 API,使其同时在多个内核中运行,提高硬件性能的利用率。 使用方法很简单,安装 M…

2.9C++多态

C 继承扩展 C继承在实际开发中它可以帮助我们实现代码重用,减少代码冗余,提高代码的可维护性和可扩展性。 通过继承,我们可以从已有的类中派生出新的类,新的类可以继承父类的属性和方法,并且可以添加自己的属性和方法…

selenium元素定位---ElementClickInterceptedException(元素点击交互异常)解决方法

目录 前言: 1、异常原因 2、解决方法: 前言: 当使用Selenium进行元素定位和交互时,可能会遇到ElementClickInterceptedException(元素点击交互异常)的异常。这通常是由于页面上存在其他元素或弹出窗口遮…

ROS学习之基础包创建的详细流程:包括rosnode, rostopic, rosrun,roslaunch等使用

0 引言 本文旨在学习ROS基础包的从零开始创建,包括如何创建一个发布消息节点,一个接收消息节点,还有如何使用roslaunch同时启动多个节点,如何编译ROS工程包等操作。 默认已在Ubuntu系统中安装ROS机器人系统,比如Ubun…

AOP--拦截器

AOP应用--拦截器Spring拦截器拦截器执行流程前缀的添加统一异常处理统一数据返回格式返回String类型 AOP应用–拦截器 AOP的作用:统一功能处理;我们将以三个内容作为学习的掌握点;而这三点也是我们非常迫切需要的 1:用户登录权限…

Windows系统分区大小

Microsoft Reserved(MSR)——保留分区——16MB左右 EFI System Partition(ESP)——系统分区——100MB左右 Recovery Partition(自起名字REP)——恢复分区——450MB左右 其他分区——剩余

对rabbitmq进行压测

添加rabbitmq依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactI…

C# PaddleOCR标注工具

基于以下开源项目改造的 https://gitee.com/BaoJianQiang/FastOCRLabel 效果 Demo下载