04-事务的四大特征,四种隔离级别,三大读,乐观锁和悲观锁

2023-12-17 11:12

本文主要是介绍04-事务的四大特征,四种隔离级别,三大读,乐观锁和悲观锁,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

事务(transaction)

四个特征ACID

一个业务通常需要多条DML(增删改)语句共同联合起来(同时成功或失败)才能完成,那么事务其实就是这个完整的业务逻辑,是一个最小的工作单元不可再分

  • 只有执行DML语句时才会考虑事务问题, 因为一旦涉及到数据的增、删、改就要考虑安全问题

MySQL默认情况下是支持自动提交事务的,即每执行一条DML语句会自动提交一次,自动提交事务并不符合我们的开发需求

  • 一个业务通常需要多条DML语句同时成功后才能提交事务,为了保证数据的安全我们需要关闭MySQL事务自动提交机制start transaction

事务在执行过程中每一条DML(增删改)的操作都会被记录到InnoDB存储引擎提供的事务性活动的日志文件中,最后根据需求决定是提交还是回滚事务

  • commit,提交事务(标志事务成功结束):,执行之前批量的DML操作然后将数据全部持久化到数据库表中,然后清空事务性活动的日志文件
  • rollback,回滚事务(标志事务失败结束): 将之前所有的DML操作全部撤销(回滚永远都是只能回滚到上一次的提交点),然后清空事务性活动的日志文件
  • 事务只能回滚insert,delete和update语句,不能回滚select,create,drop,alter这些操作因为没有任何意义

事务的四个处理过程

  • 第一步: 开启事务start transaction

  • 第二步: 执行核心业务代码包含批量的DML语句

  • 第三步: 如果核心业务代码处理过程中没有出现异常则提交事务commit

  • 第四步: 如果核心业务代码处理过程中出现异常回滚事务rollback

事务的四个特性原子性,一致性,隔离性,持久性

特性描述
Atomicity(原子性)说明事务是最小的工作单元,整个事务中的所有操作必须作为一个单元即全部完成或全部取消
Consistency(一致性)在同一个事务当中所有操作必须同时成功或失败,保证数据库从一个一致性状态转换到另一个一致性状态
Isolation(隔离性)A事务和B事务操作同一张表的时候,事务之间需要具有一定的隔离性
事务并发就是一个线程一个事务
Durability(持久性)事务一旦提交后该事务对数据库所作的更改将持久地保存在数据库之中,即使数据库发生故障也无法回滚

事务的提交与回滚

-- 使用bjpowernode数据库
mysql> use bjpowernode;
-- 查询dept_bak表中的数据        
mysql> select * from dept_bak;+--------+-------+------+| DEPTNO | DNAME | LOC  |+--------+-------+------+|     10 | abc   | bj   |+--------+-------+------+1 row in set (0.00 sec)
-- 开启事务,关闭事务的自动提交机制
mysql> start transaction;
-- 向dept_bak表中插入数据
mysql> insert into dept_bak values(20,'abc','bj');
-- 提交事务
mysql> commit;
-- 再次查看表中的数据
mysql> select * from dept_bak;+--------+-------+------+| DEPTNO | DNAME | LOC  |+--------+-------+------+|     10 | abc   | bj   ||     20 | abc   | tj   |+--------+-------+------+
-- 回滚事务只能回滚到上一次的提交点
mysql> rollback;
-- 再次查看表中的数据
mysql> select * from dept_bak;+--------+-------+------+| DEPTNO | DNAME | LOC  |+--------+-------+------+|     10 | abc   | bj   ||     20 | abc   | tj   |+--------+-------+------+

事务的隔离级别(三大读)

InnoDB存储引擎实现了四个隔离级别用以控制每个事务所做的修改.并将修改通告至其它并发的事务

名称描述
脏读在事务A中读取到了事务B未提交到数据库的数据,由于事务B可能回滚,所以事务A可能会读取到数据库中不存在的数据
不可重复读(读-读)事务B在事务A多次读取同一数据的过程中对事务A读取的数据做了更新操作并提交,导致事务A每次读取的数据都不一致
幻读(读-写)某一次的读操作得到的结果无法支撑后续的业务操作,多事务并发的情况下一定会存在幻读现象
在可重复读的情况下,事务A想插入一条id=5的记录,此时事务B把这条记录插入了并提交了事务,但是事务A看不到事务B插入的记录,结果就是事务A插入时报错了
隔离级别描述脏读不可重复读幻读加锁读
读未提交(理论级别)(READ_UNCOMMITTED)在一个事务中可以看到其他事务未提交的修改数据,大多数的数据库隔离级别都是二档起步不加锁
读已提交 (Oracle默认级别)
(READ_COMMITTED)
在一个事务中只能看到其他事务已经提交的修改数据,这种隔离级别每次读到的都是真实数据不加锁
可重复读(MySQL默认级别)
(REPEATABLE_READ)
一个事务中多次执行相同的SELECT语句得到的是相同的结果,永远读取的都是自己刚开启事务时的数据,不管其他事务是否提交了修改数据不加锁
序列化(最高隔离级别)
SERIALIZABLE
一个事务与其他事务完全地隔离,每一次读取到的数据都是最真实的,但是所有事务只能排队执行,不支持并发所以效率最低加锁

设置服务的隔离级别

设置MySQL服务默认的事务隔离级别: 在my.ini配置文件中配置[mysqld]选项的transaction-isolation属性

#该选项值可以是READ-UNCOMMITTED , READ-COMMITTED , REPEATABLE-READ , SERIALIZABLE
[mysqld]
#设置隔离级别,如果没有设置默认是REPEATABLE-READ
transaction-isolation00 = READ-COMMITTED

动态设置MySQL服务的隔离级别:SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL <isolation-level>,设置完后需退出MySQL服务重新进入

  • isolation-level(隔离级别): 隔离级别可以是READ UNCOMMITTED,READ COMMITTED,REPEATABLE READ,SERIALIZABLE

  • 全局级(GLOBAL): 设置的隔离级别对所有的会话有效

  • 会话级(SESSION): 默认设置的隔离级别只对当前的会话有效

-- 设置隔离级别为READ COMMITTED ,默认只对当前的会话有效
mysql> SET TRANSACTION ISOLATION LEVEL READ COMMITTED-- 设置会话级隔离级别为READ COMMITTED 
mysql> SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED-- 设置全局级隔离级别为READ COMMITTED :
mysql> SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED

查看MySQL服务当前的隔离级别: 服务器变量tx_isolation默认保存着当前的会话隔离级别

-- 查看当前隔离级别,默认是会话级别
mysql> SELECT @@tx_isolation;
-- 查看当前会话的隔离级别
mysql> SELECT @@session.tx_isolation;
-- 查看当前全局的隔离级别
mysql> SELECT @@global.tx_isolation;

验证四种隔离界别

验证read uncommited读未提交

事务A事务B
s1>use bjpowernode;s2>set global transaction isolation level read uncommitted;
s1>create table tx ( id int(11),num int (10));s2>use bjpowernode;
s1>start transaction;s2>start transaction;
s2>select * from tx;(空表)
s1>insert into tx values (1,10);事务A还没有提交
s2>select * from tx;事务B读取到了事务A未提交的数据
s1>rollback;
s2>select * from tx;

验证read commited读已提交

事务A事务B
s1>use bjpowernodes2> set global transaction isolation level read committed;
s1>start transaction;s2>use bjpowernode;
s2>start transaction;
s2>select * from tx;(空表)
s1>insert into tx values (1,10);
s2>select * from tx;由于事务A没有提交数据,事务B的读取的还是空表
s1>commit;事务A提交了数据
s2>select * from tx;事务B读取到了事务A已提交的数据

验证repeatable read可重复读

事务A事务B
s1>use bjpowernodes2>set global transaction isolation level repeatable read;
s1>start transaction;s2>use bjpowernode;
s2>start transaction;
s2>select * from tx;事务B开启时的数据
s1>insert into tx values (1,10);
s1>commit;事务A提交了数据
s2>select * from tx;即使事务A提交了数据,事务B读取的还是自己开启事务时的数据

验证serializable序列化

事务A事务B
s1>use bjpowernode;s2>set global transaction isolation level serializable;
s1>start transaction;s2>use bjpowernode;
select * from tx;s2>start transaction;
s1>insert into tx values (1,10);事务A在操作tx表时,只要当前事务不结束,其他事务就不能访问tx表
s2>select * from tx;事务B不能访问tx表

乐观锁和悲观锁

乐观锁: 支持事务并发,只不过需要设置给数据库中的表设置一个版本号字段

悲观锁(行级锁): 事务必须排队执行

  • 事务A在执行select语句时加上for update,表示将查询到的所有记录整行锁住,此时只要事务A不提交事务,其他事务就无法对这些记录进行修改操作

第一步: 开启一个事务A专门进行查询,并且使用行级锁锁住查询到的记录

Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
// 使用工具类获取连接对象
conn = DBUtil.getConnection();
// 将数据库的自动提交功能改为手动提交,即开启数据库事务的功能
conn.setAutoCommit(false);
// 获取预编译的数据库操作对象
String sql = "select ename from emp where job = ? for update";
ps = conn.prepareStatement(sql);
ps.setString(1, "MANAGER");
rs = ps.executeQuery();
while(rs.next()){System.out.println(rs.getString("ename"));
}
// 提交事务
conn.commit();
// 关闭资源
DBUtil.close(conn,ps,rs)

第二步: 开启一个事务B修改锁定的记录,此时发现只要事务A不结束,事务B的修改操作就无法执行

Connection conn = null;
PreparedStatement ps = null;
// 使用工具类获取连接
conn = DBUtil.getConnection();
// 关闭数据库的自动提交功能改为手动提交, 即开启数据库事务的功能
conn.setAutoCommit(false);
// 获取预编译的数据库操作对象
String sql = "update emp set sal = sal * 1.1 where job = ? ";
ps = conn.prepareStatement(sql);
ps.setString(1, "MANAGER");
int count = ps.executeUpdate();
System.out.println(rs.getString(count));
// 提交事务
conn.commit();
// 关闭资源
DBUtil.close(conn,ps,null)

这篇关于04-事务的四大特征,四种隔离级别,三大读,乐观锁和悲观锁的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/504171

相关文章

SQL Server配置管理器无法打开的四种解决方法

《SQLServer配置管理器无法打开的四种解决方法》本文总结了SQLServer配置管理器无法打开的四种解决方法,文中通过图文示例介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录方法一:桌面图标进入方法二:运行窗口进入检查版本号对照表php方法三:查找文件路径方法四:检查 S

Spring事务传播机制最佳实践

《Spring事务传播机制最佳实践》Spring的事务传播机制为我们提供了优雅的解决方案,本文将带您深入理解这一机制,掌握不同场景下的最佳实践,感兴趣的朋友一起看看吧... 目录1. 什么是事务传播行为2. Spring支持的七种事务传播行为2.1 REQUIRED(默认)2.2 SUPPORTS2

HTML5 中的<button>标签用法和特征

《HTML5中的<button>标签用法和特征》在HTML5中,button标签用于定义一个可点击的按钮,它是创建交互式网页的重要元素之一,本文将深入解析HTML5中的button标签,详细介绍其属... 目录引言<button> 标签的基本用法<button> 标签的属性typevaluedisabled

Conda虚拟环境的复制和迁移的四种方法实现

《Conda虚拟环境的复制和迁移的四种方法实现》本文主要介绍了Conda虚拟环境的复制和迁移的四种方法实现,包括requirements.txt,environment.yml,conda-pack,... 目录在本机复制Conda虚拟环境相同操作系统之间复制环境方法一:requirements.txt方法

PostgreSQL 默认隔离级别的设置

《PostgreSQL默认隔离级别的设置》PostgreSQL的默认事务隔离级别是读已提交,这是其事务处理系统的基础行为模式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录一 默认隔离级别概述1.1 默认设置1.2 各版本一致性二 读已提交的特性2.1 行为特征2.2

MySQL 事务的概念及ACID属性和使用详解

《MySQL事务的概念及ACID属性和使用详解》MySQL通过多线程实现存储工作,因此在并发访问场景中,事务确保了数据操作的一致性和可靠性,下面通过本文给大家介绍MySQL事务的概念及ACID属性和... 目录一、什么是事务二、事务的属性及使用2.1 事务的 ACID 属性2.2 为什么存在事务2.3 事务

IDEA实现回退提交的git代码(四种常见场景)

《IDEA实现回退提交的git代码(四种常见场景)》:本文主要介绍IDEA实现回退提交的git代码(四种常见场景),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1.已提交commit,还未push到远端(Undo Commit)2.已提交commit并push到

CSS 样式表的四种应用方式及css注释的应用小结

《CSS样式表的四种应用方式及css注释的应用小结》:本文主要介绍了CSS样式表的四种应用方式及css注释的应用小结,本文通过实例代码给大家介绍的非常详细,详细内容请阅读本文,希望能对你有所帮助... 一、外部 css(推荐方式)定义:将 CSS 代码保存为独立的 .css 文件,通过 <link> 标签

Spring Boot 事务详解(事务传播行为、事务属性)

《SpringBoot事务详解(事务传播行为、事务属性)》SpringBoot提供了强大的事务管理功能,通过@Transactional注解可以方便地配置事务的传播行为和属性,本文将详细介绍Spr... 目录Spring Boot 事务详解引言声明式事务管理示例编程式事务管理示例事务传播行为1. REQUI

MySQL中的事务隔离级别详解

《MySQL中的事务隔离级别详解》在MySQL中,事务(Transaction)是一个执行单元,它要么完全执行,要么完全回滚,以保证数据的完整性和一致性,下面给大家介绍MySQL中的事务隔离级别详解,... 目录一、事务并发问题二、mysql 事务隔离级别1. READ UNCOMMITTED(读未提交)2