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

数据库的事务

事务

  • 事务的概述
  • 事务的特性
  • 在MySQL中操作事务
    • 命令式显式开启事务
    • 关闭自动提交(全局设置式)
  • 事务的隔离级别
    • Read uncommitted
    • Read committed
    • Repeatable read
    • Serializable

事务的概述

事务(Transaction)是数据库管理系统(DBMS)中,被封装为单个逻辑工作单元的一系列数据库操作(如查询、插入、更新、删除等)的集合。事务确保确保要么所有操作均成功执行并永久生效(提交),要么任一操作失败时,所有已执行的操作均被撤销,数据库恢复到事务开始前的状态(回滚)。事务旨在维护数据库的完整性、一致性和可靠性,即使在系统故障或并发访问的情况下也是如此。

经典示例:银行转账
假设用户 A 向用户 B 转账 100 元,这个过程包含两条核心 SQL 操作:
从 A 的账户扣除 100 元:UPDATE account SET balance = balance - 100 WHERE id = ‘A’;
向 B 的账户增加 100 元:UPDATE account SET balance = balance + 100 WHERE id = ‘B’;
这两条操作必须构成一个事务:
若两条都执行成功,事务提交(COMMIT),数据生效;
若任意一条失败,事务回滚(ROLLBACK),A 被扣的 100 元恢复。

事务的特性

  • 原子性(Atomicity):事务中的所有操作是一个不可拆分的原子单元,不存在部分执行的中间状态。要么全部成功,要么全部回滚,不会因故障导致操作一半的情况。
  • 一致性(Consistency):事务执行后,数据库状态与业务规则保持一致。例如转账业务,无论事务执行成功与否,参与转账的两个账号余额之和应该是不变的。
  • 隔离性(Isolation):多个事务同时执行时,彼此的操作互不干扰。DBMS 通过隔离级别控制并发事务的可见性,避免脏读、不可重复读、幻读等问题。
  • 持久性(Durability):一旦事务提交成功,事务中所有的数据操作都被持久化到数据库中,即使提交事务后,数据库马上崩溃,在数据库重启时,也必须能保证通过某种机制恢复数据

在MySQL中操作事务

命令式显式开启事务

第一种方式是命令式显式开启事务,通过 start transaction; 显式声明事务的开始,后续操作作为事务内的逻辑单元,最终通过 commit 或 rollback 结束事务。

示例:
commit
在这里插入图片描述
rollback
在这里插入图片描述

一旦commit,即提交事务,事务结束,数据永久的保存到数据库中
一旦roolback,即回滚事务,事务结束,数据回滚到最初始化的状态

事务边界清晰,通过 start transaction 和 commit / rollback 明确控制事务的状态。每次事务需手动开启,适用于临时、单次的事务操作。

关闭自动提交(全局设置式)

第二种方式是关闭自动提交,MySQL 默认开启 autocommit(自动提交),即每条 SQL 语句会被自动封装为一个独立事务并立即提交。
show variables like '%commit%'; 查看事务的是事务是否是默认提交,通过关闭自动提交 set autocommit = off;,可将多条 SQL 纳入同一个事务,直到手动提交或回滚。

示例:
commit
在这里插入图片描述
rollback
在这里插入图片描述

若需恢复默认行为,执行 set autocommit = on; 或关闭此cmd窗口

一次设置影响后续所有 SQL,无需重复开启事务,适用于批量、连续的事务操作。若未手动提交 / 回滚而断开连接,MySQL 会自动回滚事务,避免数据不一致。

在 Java 中通过 JDBC 操作事务时,与 MySQL 操作一致默认自动提交,核心是通过 Connection 对象控制事务。void setAutoCommit(boolean autoCommit) 如果传入了false,即设置MySQL数据库的事务不默认提交,void commit() 提交事务,void rollback() 回滚事务

补充:在 Java 中通过 JDBC 操作事务时,JDBC 规范默认将连接(Connection)的事务设置为自动提交模式(即 autoCommit 默认为 true),这与 MySQL 数据库默认的一致。但本质是 JDBC 连接级别的控制,仅影响当前 Connection 对象,不会修改数据库全局的 autocommit 配置。

事务的隔离级别

不考虑事务的隔离性会引发的问题

  • 脏读:一个事务在执行过程中,读取到了另一个尚未提交的事务对数据的修改结果;
  • 不可重复读:在同一个事务的生命周期内,对同一条数据进行多次读取,期间另一个事务对该数据执行了修改并提交的操作,导致事务多次读取的结果不一致;
  • 虚度(幻读):在同一个事务的生命周期内,对同一范围条件的数据进行多次查询,期间另一个事务执行了插入或删除符合该范围条件的记录并提交的操作,导致事务多次查询的结果集不一致。

设置事务的隔离级别

  • 事务的隔离级别,查询隔离级别 select @@tx_isolation;
    Read uncommitted ‐‐ 什么都解决不了
    Read committed ‐‐ 避免脏读,但是不可重复读和虚读有可能产生
    Repeatable read ‐‐ 避免脏读和不可重复读,虚度有可能产生的
    Serializable ‐‐ 避免各种读
  • 四种隔离级别的安全性和效率
    安全:Serializable > Repeatable read > Read committed > Read uncommitted
    效率:Serializable < Repeatable read < Read committed < Read uncommitted
  • 数据库默认的隔离级别
    MySQL的数据库,默认的隔离级别是Repeatable read,避免脏读和不可重复读

下面我们来具体演示不同的事务隔离级别产生的不同效果

Read uncommitted

开启两个窗口,一个A窗口(左),一个B窗口(右)
设置A窗口的隔离级别为最低级别 set session transaction isolation level read uncommitted;,在两个窗口中,都开启事物 start transaction;,在B窗口中完成转账的工作 update account set money = money - 100 where name = ‘熊二’;,注意B窗口的事务未提交,在A窗口中查询结果集

在这里插入图片描述

发现产生了脏读,一个事务读取到了另一个事物未提交的数据

此时B窗口回滚事务,在A窗口中查询结果集

在这里插入图片描述

A与B窗口读到的均是事务回滚后的数据集

我们继续演示,A与B均开启事务,在B窗口中完成转账的工作 update account set money = money - 100 where name = ‘熊二’;,B窗口提交事务,A窗口不提交,在A窗口中查询结果集

在这里插入图片描述

发现产生了不可重复读,一个事务读取到了另一个事务提交的修改数据,导致了多次查询的结果不一致

我们继续演示,A与B均开启事务,在B窗口中添加一条数据 insert into account values (null,‘小苍’,1000); ,B窗口提交事务,A窗口不提交,在A窗口中查询结果集

在这里插入图片描述

发现产生了虚读(幻读),一个事务读取到了另一个事务提交的新增数据,导致了多次查询的结果不一致

Read committed

开启两个窗口,一个A窗口(左),一个B窗口(右)
设置A窗口的隔离级别为 set session transaction isolation level read committed;,在两个窗口中,都开启事物 start transaction;,在B窗口中完成转账的工作 update account set money = money - 100 where name = ‘熊二’;,注意B窗口的事务未提交,在A窗口中查询结果集

在这里插入图片描述

发现避免了脏读

我们继续演示,B窗口提交事务,A窗口不提交,在A窗口中查询结果集

在这里插入图片描述

发现产生了不可重复读,一个事务读取到了另一个事务提交的修改数据,导致了多次查询的结果不一致

此时A窗口也提交事务

在这里插入图片描述

A与B窗口读到的均是事务提交后的数据集

我们继续演示,A与B均开启事务,在B窗口中添加一条数据 insert into account values (null,‘小羊’,1000); ,B窗口提交事务,A窗口不提交,在A窗口中查询结果集

在这里插入图片描述

发现产生了虚读(幻读),一个事务读取到了另一个事务提交的新增数据,导致了多次查询的结果不一致

Repeatable read

开启两个窗口,一个A窗口(左),一个B窗口(右)
设置A窗口的隔离级别为 set session transaction isolation level repeatable read;,在两个窗口中,都开启事物 start transaction;,在B窗口中完成转账的工作 update account set money = money - 100 where name = ‘熊二’;,B窗口的事务未提交,在A窗口中查询结果集,以及B窗口的事务提交A未提交,在A窗口中查询结果集

在这里插入图片描述

发现避免了脏读和不可重复读

我们继续演示,A与B均开启事务,在B窗口中添加一条数据 insert into account values (null,‘小牛’,1000); ,B窗口提交事务,A窗口不提交

在这里插入图片描述

在A窗口中查询结果集,没有显示第30行数据,但是在第30行无法添加数据,即第30行数据已被占用。即产生了虚读(幻读),一个事务读取到了另一个事务提交的新增数据,导致了多次查询的结果不一致。

Serializable

开启两个窗口,一个A窗口(左),一个B窗口(右)
设置A窗口的隔离级别为 set session transaction isolation level serializable;,在两个窗口中,都开启事务 start transaction;

在这里插入图片描述

B窗口中执行新增操作 insert into account values (null,‘小小’,1100);,无法执行成功,在A窗口中查询结果集没有该数据,A窗口的事务提交后B窗口再次执行新增操作才可以成功,Serializable 避免了幻读。


文章转载自:

http://2DNA6sic.psxcr.cn
http://V3QFVQJC.psxcr.cn
http://mSFa14EJ.psxcr.cn
http://0oq5UbHm.psxcr.cn
http://7m03d2Pa.psxcr.cn
http://2Q4LChOL.psxcr.cn
http://RnFJwNR8.psxcr.cn
http://4ZFa1ZtZ.psxcr.cn
http://p4KMBGrp.psxcr.cn
http://qtwmBBz2.psxcr.cn
http://0Xi4ejvx.psxcr.cn
http://SMUmwwqn.psxcr.cn
http://U66EdbBH.psxcr.cn
http://rYyR6ADE.psxcr.cn
http://OvkqA231.psxcr.cn
http://DUo6w3vU.psxcr.cn
http://fyYyUi8y.psxcr.cn
http://0oH6ugUU.psxcr.cn
http://WERCqPze.psxcr.cn
http://our7s4y9.psxcr.cn
http://svWR9K6l.psxcr.cn
http://SLduoQmc.psxcr.cn
http://gTFBpqme.psxcr.cn
http://f1vjWjec.psxcr.cn
http://4EYuafSm.psxcr.cn
http://WjHj9KJ6.psxcr.cn
http://5EKPfKi9.psxcr.cn
http://vnUCMkEu.psxcr.cn
http://HbmDW32M.psxcr.cn
http://SQ9CkyRV.psxcr.cn
http://www.dtcms.com/a/388562.html

相关文章:

  • Cadence SPB 2025安装教程(附安装包)Cadence SPB 24.1下载详细安装图文教程
  • .NET Framework 4.8 多线程编程
  • qt QHorizontalPercentBarSeries详解
  • 软考中级习题与解答——第七章_数据库系统(3)
  • Redis(基础数据类型/String)
  • python的面试题
  • 内聚和耦合基础
  • Java基本类型与包装类在MyBatis中的应用指南
  • 《Unity3D VR游戏手柄振动与物理碰撞同步失效问题深度解析》
  • 基于 Rust 的 CAD 工具demo示例
  • 多模态大模型研究每日简报【2025-09-17】
  • 2D平台动作游戏《Haneda Girl》推出免费体验版
  • 《艾尔登法环:黑夜君临》DLC泄露:更多角色和Boss!
  • 向量化执行引擎是啥?
  • LeetCode 刷题【81. 搜索旋转排序数组 II、82. 删除排序链表中的重复元素 II、83. 删除排序链表中的重复元素】
  • 关于二叉树的OJ练习
  • STM32H743-ARM例程1-GPIO点亮LED
  • 25.9.16幂等性总结
  • 27、Transformer架构详解-序列建模的革命性突破
  • [从青铜到王者] Spring Boot+Redis+Kafka电商场景面试全解析
  • 基于el-upload和vue-cropper实现图片上传裁剪组件
  • Kettle时间戳转换为日期格式处理方式
  • go.js Panel中文API
  • 加密货币中的MEV是什么
  • 【Linux学习笔记】线程概念与控制(一)
  • Linux笔记---非阻塞IO与多路复用
  • 生物信息学中的 AI Agent: Codex 初探
  • 贪心算法应用:埃及分数问题详解
  • 力扣hot100刷题day1
  • 什么是跨站脚本攻击