从 01 开始 从 01 开始
首页
  • 📚 计算机基础

    • 计算机简史
    • 数字电路
    • 计算机组成原理
    • 操作系统
    • Linux
    • 计算机网络
    • 数据库
    • 编程工具
    • 装机
  • 🎨 前端

    • Node
  • JavaSE
  • Java 高级
  • JavaEE

    • 构建、依赖管理
    • Ant
    • Maven
    • 日志框架
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • 环境管理和配置管理-科普篇
    • Servlet
  • Spring

    • Spring基础
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC

    • SpringMVC 基础
  • SpringBoot

    • SpringBoot 基础
  • Windows 使用技巧
  • 手机相关技巧
  • 最全面的输入法教程
  • 最全面的浏览器教程
  • Office
  • 图片类工具
  • 效率类工具
  • 最全面的 RSS 教程
  • 码字工具
  • 各大平台
  • 校招
  • 五险一金
  • 职场规划
  • 关于离职
  • 杂谈
  • 自媒体
  • 📖 读书

    • 读书工具
    • 走进科学
  • 🌍 英语

    • 从零开始学英语
    • 英语兔的相关视频
    • Larry 想做技术大佬的相关视频
  • 🏛️ 政治

    • 反腐
    • GFW
    • 404 内容
    • 审查与自我审查
    • 互联网
    • 战争
    • 读书笔记
  • 💰 经济

    • 关于税
    • 理财
  • 💪 健身

    • 睡眠
    • 皮肤
    • 口腔健康
    • 学会呼吸
    • 健身日志
  • 🏠 其他

    • 驾驶技能
    • 租房与买房
    • 厨艺
  • 电影

    • 电影推荐
  • 电视剧
  • 漫画

    • 漫画软件
    • 漫画推荐
  • 游戏

    • Steam
    • 三国杀
    • 求生之路
  • 小说
  • 关于本站
  • 关于博主
  • 打赏
  • 网站动态
  • 友人帐
  • 从零开始搭建博客
  • 搭建邮件服务器
  • 本站分享
  • 🌈 生活

    • 2022
    • 2023
    • 2024
    • 2025
  • 📇 文章索引

    • 文章分类
    • 文章归档

晓林

程序猿,自由职业者,博主,英语爱好者,健身达人
首页
  • 📚 计算机基础

    • 计算机简史
    • 数字电路
    • 计算机组成原理
    • 操作系统
    • Linux
    • 计算机网络
    • 数据库
    • 编程工具
    • 装机
  • 🎨 前端

    • Node
  • JavaSE
  • Java 高级
  • JavaEE

    • 构建、依赖管理
    • Ant
    • Maven
    • 日志框架
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • 环境管理和配置管理-科普篇
    • Servlet
  • Spring

    • Spring基础
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC

    • SpringMVC 基础
  • SpringBoot

    • SpringBoot 基础
  • Windows 使用技巧
  • 手机相关技巧
  • 最全面的输入法教程
  • 最全面的浏览器教程
  • Office
  • 图片类工具
  • 效率类工具
  • 最全面的 RSS 教程
  • 码字工具
  • 各大平台
  • 校招
  • 五险一金
  • 职场规划
  • 关于离职
  • 杂谈
  • 自媒体
  • 📖 读书

    • 读书工具
    • 走进科学
  • 🌍 英语

    • 从零开始学英语
    • 英语兔的相关视频
    • Larry 想做技术大佬的相关视频
  • 🏛️ 政治

    • 反腐
    • GFW
    • 404 内容
    • 审查与自我审查
    • 互联网
    • 战争
    • 读书笔记
  • 💰 经济

    • 关于税
    • 理财
  • 💪 健身

    • 睡眠
    • 皮肤
    • 口腔健康
    • 学会呼吸
    • 健身日志
  • 🏠 其他

    • 驾驶技能
    • 租房与买房
    • 厨艺
  • 电影

    • 电影推荐
  • 电视剧
  • 漫画

    • 漫画软件
    • 漫画推荐
  • 游戏

    • Steam
    • 三国杀
    • 求生之路
  • 小说
  • 关于本站
  • 关于博主
  • 打赏
  • 网站动态
  • 友人帐
  • 从零开始搭建博客
  • 搭建邮件服务器
  • 本站分享
  • 🌈 生活

    • 2022
    • 2023
    • 2024
    • 2025
  • 📇 文章索引

    • 文章分类
    • 文章归档
  • 计算机简史

  • 数字电路

  • 计算机组成原理

  • 操作系统

  • Linux

  • 计算机网络

  • 数据库

    • 教程概述
    • 数据的存储
    • 数据库的安装
    • 数据库的启停与连接
    • 数据库的管理
    • SQL 概述
    • 表的管理
    • SELECT 基础
    • 运算符
    • 聚合查询
    • 数据的排序
    • 数据的插入
    • 数据的删除
    • 数据的更新
    • 事务
      • 有事务之前
      • 创建事务
      • COMMIT:提交处理
      • ROLLBACK:取消处理
      • 事务处理何时开始
      • ACID 特性
    • 视图
    • 子查询
    • 函数
    • 谓词
    • CASE 表达式
    • 集合运算
    • 联结查询-JOIN
    • SQL 入门小结
    • 更多数据库
    • MySQL 的数据类型
    • 命令行的一些用法
    • 用户与权限管理
    • MySQL 的权限管理
    • mysqldump
    • mysqladmin
    • Liquibase
    • 表注释与字段注释
    • 编码类型
  • 编程工具

  • 装机

  • 计算机基础
  • 数据库
2023-11-24
目录

事务

# 130.事务

在 DBMS 中,事务(transaction)是非常重要的概念。

‍ ‍

# 有事务之前

举例,店铺决定把运动 T 恤的销售单价下调 1000 日元,同时把 T 恤衫的销售单价上浮 1000 日元,那么使用 update 即可。

① 首先将运动 T 恤的销售单价降低 1000 日元

UPDATE Product
   SET sale_price = sale_price - 1000
 WHERE product_name = '运动T恤';
1
2
3

‍ ② 再将 T 恤衫的销售单价上浮 1000 日元

UPDATE Product
   SET sale_price = sale_price + 1000
 WHERE product_name = 'T恤衫';
1
2
3

‍ 如果只执行了 ① 的操作而忘记了执行 ② 的操作,或者反过来只执行了 ② 的操作而忘记了执行 ① 的操作,那么更新就算失败的。

再来考虑一个例子:账户 A 给账户 B 赚钱 100,先从账户 A 减去 100,再去账户 B 增加 100,如果有一个更新失败,那么就会造成财产的损失。

遇到这种需要执行一系列更新操作的情况,一定要使用事务来进行处理。

# 创建事务

基本语法:

事务开始语句;

      DML语句①;
      DML语句②;
      DML语句③;
         .
         .
         .
事务结束语句(COMMIT或者ROLLBACK);
1
2
3
4
5
6
7
8
9

使用事务开始语句和事务结束语句,将一系列 DML 语句(INSERT/UPDATE/DELETE 语句)括起来,就实现了一个事务处理。

这时需要特别注意的是事务的开始语句 。实际上,在标准 SQL 中并没有定义事务的开始语句,而是由各个 DBMS 自己来定义的。比较有代表性的语法如下所示。

与之相对,事务结束语句只有 COMMIT 和 ROLLBACK 两种,在所有的 RDBMS 中都是通用的。

--SQL Server、PostgreSQL
BEGIN TRANSACTION

--MySQL
START TRANSACTION

--Oracle、DB2
无
1
2
3
4
5
6
7
8

‍ 例如使用之前的那两个 UPDATE (① 和 ②)创建出的事务:

--SQL Server  PostgreSQL
BEGIN TRANSACTION;
    -- 将运动T恤的销售单价降低1000日元
    UPDATE Product
       SET sale_price = sale_price - 1000
     WHERE product_name = '运动T恤';

    -- 将T恤衫的销售单价上浮1000日元
    UPDATE Product
       SET sale_price = sale_price + 1000
     WHERE product_name = 'T恤衫';
COMMIT;




--MySQL
START TRANSACTION;

    -- 将运动T恤的销售单价降低1000日元
    UPDATE Product
       SET sale_price = sale_price - 1000
     WHERE product_name = '运动T恤';

    -- 将T恤衫的销售单价上浮1000日元
    UPDATE Product
       SET sale_price = sale_price + 1000
     WHERE product_name = 'T恤衫';

COMMIT;




--Oracle  DB2
-- 将运动T恤的销售单价降低1000日元
UPDATE Product
   SET sale_price = sale_price - 1000
 WHERE product_name = '运动T恤';

-- 将T恤衫的销售单价上浮1000日元
UPDATE Product
   SET sale_price = sale_price + 1000
 WHERE product_name = 'T恤衫';

COMMIT;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

如上所示,各个 DBMS 事务的开始语句都不尽相同,其中 Oracle 和 DB2 并没有定义特定的开始语句。

反之,事务的结束需要用户明确地给出指示。结束事务的指令有 commit 和 rollback ‍

# COMMIT:提交处理

COMMIT 是提交事务包含的全部更新处理的结束指令。一旦提交 ,就无法恢复到事务开始前的状态了。因此,在提交之前一定要确认是否真的需要进行这些更新。

​​ ‍

注意:一旦提交,就很难恢复到之前的数据了,就好比 delete 一样,删除后就很难恢复了。 ‍

# ROLLBACK:取消处理

ROLLBACK 是取消事务包含的全部更新处理的结束指令。一旦回滚 ,数据库就会恢复到事务开始之前的状态。通常回滚并不会像提交那样造成大规模的数据损失。

​​ ‍

代码清单 4-22 事务回滚的例子

--SQL Server  PostgreSQL
BEGIN TRANSACTION; ------------------- ①

    -- 将运动T恤的销售单价降低1000日元
    UPDATE Product
       SET sale_price = sale_price - 1000
     WHERE product_name = '运动T恤';

    -- 将T恤衫的销售单价上浮1000日元
    UPDATE Product
       SET sale_price = sale_price + 1000
     WHERE product_name = 'T恤衫';

ROLLBACK;
1
2
3
4
5
6
7
8
9
10
11
12
13
14

上述事务处理执行之后,表中的数据不会发生任何改变。这是因为执行最后一行的 ROLLBACK 之后,所有的处理都被取消了。因此,回滚执行起来就无需像提交时那样小心翼翼了(即使是想要提交的情况,也只需要重新执行事务处理就可以了)。 ‍ 注意:不能回退 select 子句(回退了也没意思),也不能回退 create 和 drop 操作,事务中可以使用这些语句,但进行回退时,这些操作也不撤销 ‍

# 事务处理何时开始

之前我们说过,事务并没有标准的开始指令存在,而是根据 DBMS 的不同而不同。

实际上,几乎所有的数据库产品的事务都无需开始指令。这是因为大部分情况下,事务在数据库连接建立时就已经悄悄开始了,并不需要用户再明确发出开始指令。例如,使用 Oracle 时,数据库连接建立之后,第一条 SQL 语句执行的同时,事务就已经悄悄开始了。

像这样不使用指令而悄悄开始事务的情况下,应该如何区分各个事务呢?通常会有如下两种情况。

  • 每条 SQL 语句就是一个事务(自动提交模式,auto commit)
  • 直到用户执行 COMMIT 或者 ROLLBACK 为止算作一个事务

通常的 DBMS 都可以选择其中任意一种模式。默认使用自动提交模式的 DBMS 有 SQL Server 、PostgreSQL 和 MySQL 等。 DML 语句如下所示,每一条语句都括在事务的开始语句和结束语句之中。

BEGIN TRANSACTION;
    -- 将运动T恤的销售单价降低1000日元
    UPDATE Product
       SET sale_price = sale_price - 1000
     WHERE product_name = '运动T恤';
COMMIT;

BEGIN TRANSACTION;
    -- 将T恤衫的销售单价上浮1000日元
    UPDATE Product
       SET sale_price = sale_price + 1000
     WHERE product_name = 'T恤衫';
COMMIT;
1
2
3
4
5
6
7
8
9
10
11
12
13

例如,PostgreSQL 的用户手册中有如下记述:“PostgreSQL 中所有的 SQL 指令语句都在事务内执行。即使不执行 BEGIN ,这些命令语句也会在执行时悄悄被括在 BEGIN 和 COMMIT (如果成功的话)之间。”(《PostgreSQL 9.5.2 文档》“3-4 节事务”) ‍ 在默认使用 B 模式的 Oracle 中,事务都是直到用户自己执行提交或者回滚指令才会结束。

自动提交的情况需要特别注意的是 DELETE 语句。如果不是自动提交,即使使用 DELETE 语句删除了数据表,也可以通过 ROLLBACK 命令取消该事务的处理,恢复表中的数据。但这仅限于明示开始事务,或者关闭自动提交的情况。如果不小心在自动提交模式下执行了 DELETE 操作,即使再回滚也无济于事了。这是一个很严重的问题,初学者难免会碰到这样的麻烦。 ‍

# ACID 特性

DBMS 的事务都遵循四种特性,将这四种特性的首字母结合起来统称为 ACID 特性 。这是所有 DBMS 都必须遵守的规则。

# 原子性(Atomicity)

原子性是指在事务结束时,其中所包含的更新处理要么全部执行,要么完全不执行,也就是要么占有一切要么一无所有。例如,在之前的例子中,在事务结束时,绝对不可能出现运动 T 恤的价格下降了,而 T 恤衫的价格却没有上涨的情况。该事务的结束状态,要么是两者都执行了(COMMIT ),要么是两者都未执行(ROLLBACK )。

从事务中途停止的角度去考虑,就能比较容易理解原子性的重要性了。由于用户在一个事务中定义了两条 UPDATE 语句,DBMS 肯定不会只执行其中一条,否则就会对业务处理造成影响。


# 一致性(Consistency)

一致性指的是事务中包含的处理要满足数据库提前设置的约束,如主键约束或者 NOT NULL 约束等。例如,设置了 NOT NULL 约束的列是不能更新为 NULL 的,试图插入违反主键约束的记录就会出错,无法执行。对事务来说,这些不合法的 SQL 会被回滚。也就是说,这些 SQL 处理会被取消,不会执行。

一致性也称为完整性 。

​​ ‍

# 隔离性(Isolation)

隔离性指的是保证不同事务之间互不干扰的特性。该特性保证了事务之间不会互相嵌套。此外,在某个事务中进行的更改,在该事务结束之前,对其他事务而言是不可见的。因此,即使某个事务向表中添加了记录,在没有提交之前,其他事务也是看不到新添加的记录的。 ‍

# 持久性(Durability)

持久性也可以称为耐久性,指的是在事务(不论是提交还是回滚)结束后,DBMS 能够保证该时间点的数据状态会被保存的特性。即使由于系统故障导致数据丢失,数据库也一定能通过某种手段进行恢复。

如果不能保证持久性,即使是正常提交结束的事务,一旦发生了系统故障,也会导致数据丢失,一切都需要从头再来。

保证持久性的方法根据实现的不同而不同,其中最常见的就是将事务的执行记录保存到硬盘等存储介质中(该执行记录称为日志 )。当发生故障时,可以通过日志恢复到故障发生前的状态。 ‍ (完)

上次更新: 2025/5/9 14:55:39
数据的更新
视图

← 数据的更新 视图→

最近更新
01
学点统计学:轻松识破一本正经的胡说八道
06-05
02
2025 年 5 月记
05-31
03
《贫穷的本质》很棒,但可能不适合你
05-27
更多文章>
Theme by Vdoing | Copyright © 2022-2025 | 粤 ICP 备 2022067627 号 -1 | 粤公网安备 44011302003646 号 | 点击查看十年之约
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式