深入理解数据库事务(超详细)

一、事务的介绍

事务是一组操作的集合,事务会把所有操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。 

二、事务的基本操作

2.1  事务操作方式一

 例子:    转账场景(张三向李四转账)

  1. -- 1. 查询张三账户余额
  2. select * from account where name = '张三';
  3. -- 2. 将张三账户余额-1000
  4. update account set money = money - 1000 where name = '张三';
  5. -- 此语句出错后张三钱减少但是李四钱没有增加
  6. 模拟sql语句错误
  7. -- 3. 将李四账户余额+1000
  8. update account set money = money + 1000 where name = '李四';
  9. -- 查看事务提交方式
  10. SELECT @@AUTOCOMMIT;
  11. -- 设置事务提交方式,1为自动提交,0为手动提交,该设置只对当前会话有效
  12. SET @@AUTOCOMMIT = 0;
  13. -- 提交事务
  14. COMMIT;
  15. -- 回滚事务
  16. ROLLBACK;
  17. -- 设置手动提交后上面代码改为:
  18. select * from account where name = '张三';
  19. update account set money = money - 1000 where name = '张三';
  20. update account set money = money + 1000 where name = '李四';
  21. commit;

2.2  事务操作方式二

 开启事务:
  START TRANSACTION 或 BEGIN TRANSACTION;
提交事务:
  COMMIT;
回滚事务:
  ROLLBACK;

操作实例:

  1. start transaction;
  2. select * from account where name = '张三';
  3. update account set money = money - 1000 where name = '张三';
  4. update account set money = money + 1000 where name = '李四';
  5. commit;

2.3  实际开发的案例 

一个实际开发中常见的例子是银行系统中的转账业务。在进行资金转移时,我们需要保证转出和转入两个账户的金额变动是原子性的,要么全部成功,要么全部失败。

以下是一个示例代码片段:

// 假设有两个账户:accountA 和 accountB
String accountA = "A";
String accountB = "B";
double transferAmount = 100.0; // 转账金额// 获取数据库连接
Connection connection = getConnection();
try {connection.setAutoCommit(false); // 设置手动提交事务// 查询账户 A 的余额double balanceA = queryBalance(accountA);// 查询账户 B 的余额double balanceB = queryBalance(accountB);if (balanceA >= transferAmount) { // 检查账户 A 的余额是否足够// 扣除账户 A 的金额updateBalance(connection, accountA, balanceA - transferAmount);// 增加账户 B 的金额updateBalance(connection, accountB, balanceB + transferAmount);connection.commit(); // 提交事务System.out.println("转账成功!");} else {System.out.println("转账失败:账户 A 余额不足!");}
} catch (SQLException e) {connection.rollback(); // 发生异常,回滚事务System.out.println("转账失败:" + e.getMessage());
} finally {connection.close(); // 关闭数据库连接
}

在上述示例中,我们使用connection.setAutoCommit(false)将自动提交事务的选项关闭,并手动控制事务的提交和回滚。当余额足够时,我们更新账户 A 和账户 B 的余额,并使用connection.commit()提交事务。如果发生异常或余额不足的情况,我们使用connection.rollback()回滚事务。

通过使用事务,我们可以确保转账过程中的数据一致性和可靠性。只有当两个账户的金额都成功更新后,才会执行事务的提交操作,否则会回滚到事务开始前的状态。

这是一个简单的示例,实际应用中可能涉及更多复杂的业务逻辑和错误处理。但这个例子展示了如何在实际开发中使用START TRANSACTIONBEGIN来管理事务,确保转账操作的一致性和可靠性。

三、事务的四大特性

  • 原子性(Atomicity):事务是不可分割的最小操作但愿,要么全部成功,要么全部失败
  • 一致性(Consistency):事务完成时,必须使所有数据都保持一致状态
  • 隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行
  • 持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的

四、并发事务问题

问题描述
脏读一个事务读到另一个事务还没提交的数据
不可重复读一个事务先后读取同一条记录,但两次读取的数据不同
幻读一个事务按照条件查询数据时,没有对应的数据行,但是再插入数据时,又发现这行数据已经存在

常用的并发控制机制包括:

  1. 锁(Locking):使用锁来控制并发事务对数据的访问和修改,确保在某个事务读取或修改数据时,其他事务不能同时进行相同的操作。

  2. 事务隔离级别(Isolation Level):通过设置不同的事务隔离级别,定义了事务之间的可见性、并发控制的粒度等规则。

  3. 多版本并发控制(MVCC):每个事务在读取数据时,会看到一个特定的版本,而不是直接读取最新的数据。这样可以避免脏读、不可重复读和幻读问题。

  4. 时间戳排序(Timestamp Ordering):使用时间戳来对事务进行排序,根据时间戳来判断事务的执行顺序,确保事务按照正确的顺序读取和修改数据。

实际开发中,为了解决并发事务问题,需要根据具体情况选择适当的并发控制机制和事务隔离级别,并进行合理的设计和优化。同时,也需要进行充分的测试和验证,确保系统在高并发环境下依然能够保持数据的一致性和可靠性。

五、事务的隔离级别

并发事务隔离级别:

隔离级别脏读不可重复读幻读
Read uncommitted(读未提交)
Read committed(读已提交)×
Repeatable Read(可重复读)(默认的隔离级别)××
Serializable(串行化)×××
  • √表示在当前隔离级别下该问题会出现
  • Serializable 性能最低;Read uncommitted 性能最高,数据安全性最差

注意:事务隔离级别越高,数据越安全,但是性能越低。


 查看事务隔离级别:
  SELECT @@TRANSACTION_ISOLATION;
设置事务隔离级别:
  SET [ SESSION | GLOBAL ] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE };
     SESSION 是会话级别,表示只针对当前会话有效,GLOBAL 表示对所有会话有效

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

高性能MySQL实战(一):表结构

大家好,我是 方圆。最近因需求改动新增了一些数据库表,但是在定义表结构时,具体列属性的选择有些不知其所以然,索引的添加也有遗漏和不规范的地方,所以我打算为创建一个高性能表的过程以实战的形式写一个专题&#xff…

Element-UI简介

目录 安装 常用组件 Container 布局容器 Button 按钮 MessageBox 弹框 Form 表单验证 element-ui是一个前端的ui框架,封装了很多已经写好的ui组件,例如表单组件,布局组件,表格组件.......是一套桌面端组件。 Element - 网站…

华为PMS API client token auth failed

对接华为pms时出现问题,提示华为PMS API client token auth failed 主要是权限的问题,创建项目的时候选择N/A

11. 使用tomcat中碰到的一些问题

文章目录 问题一:Tomcat的startup.bat启动后出现乱码问题二:一闪而退之端口占用问题三:非端口问题的一闪而退问题四:服务器的乱码和跨域问题问题五: 在tomcat\webapps\下创建文件夹为什么tomcat重启就会丢失问题六:Tom…

无脑入门pytorch系列(一)—— nn.embedding

本系列教程适用于没有任何pytorch的同学(简单的python语法还是要的),从代码的表层出发挖掘代码的深层含义,理解具体的意思和内涵。pytorch的很多函数看着非常简单,但是其中包含了很多内容,不了解其中的意思…

Android中级——RemoteView

RemoteView RemoteView的应用NotificationWidgetPendingIntent RemoteViews内部机制模拟RemoteViews RemoteView的应用 Notification 如下开启一个系统的通知栏,点击后跳转到某网页 public class MainActivity extends AppCompatActivity {private static final …

layui之layer弹出层的icon数字及效果展示

layer的icon样式 icon如果在信息提示弹出层值(type为0)可以传入0-6,icon与图标对应关系如下: 如果是加载层(type为3)可以传入0-2,icon与图标对应关系如下:

无涯教程-Lua - 嵌套if语句函数

在Lua编程中,您可以在另一个if or else if语句中使用一个if or else if语句。 nested if statements - 语法 嵌套if 语句的语法如下- if( boolean_expression 1) then--[ Executes when the boolean expression 1 is true --]if(boolean_expression 2)then--[ Ex…

通过C语言设计的推箱子(控制台终端)

一、项目介绍 推箱子游戏是一款经典的益智小游戏,玩家需要控制主角角色将几个木箱按照要求推到指定位置。在控制台终端中,可以使用字符来表示不同的游戏元素,例如 ‘#’ 表示墙壁, ’ ’ 表示空地, ‘$’ 表示木箱&am…

在服务器上搭建gitlab

目录 1.在服务器上下载gitlab 2.编辑站点位置 3.重载配置 4.访问gitlab 最终效果展示: 官方文档: 安装部署GitLab服务 1.在服务器上下载gitlab wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-12.9.0-ce.0.el7.x86_64.r…

C. Mark and His Unfinished Essay - 思维

分析: 直接模拟操作会mle,可以每次复制记录对应源字符串的下标,可以记录每次字符串增加的长度的左右端点下标,可以发现左端点与读入的l是对应的,因此就可以向前移到l的位置,这样层层递归,就能找…

设计模式之适配器模式

一、概述 将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 二、适用性 1.你想使用一个已经存在的类,而它的接口不符合你的需求。 2.你想创建一个可以复用的类,该类可以与其他不…

el-popover使用自定义图标

使用el-popover实现鼠标点击或浮动到自定义图标上弹出表格弹窗,官方文档上使用的是按钮el-button,如果想换成图标或其他的组件的话直接把el-button替换掉即可。注意替换之后的组件一定要加slot“reference”,不然组件是显示不出来的。 代码如…

ProxyGenerator-代理类生成器

ProxyGenerator是JDK-sun包下提供的用于生成动态代理类信息的类,其唯一向外透出的是其静态方法-generateProxyClass(…)。 public class ProxyGenerator { ... }学习本篇文章,就是想学习ProxyGenerator如何生成代理类信息的过程。 一、唯一入口-公开静…

Misc取证学习

文章目录 Misc取证学习磁盘取证工具veracryto挂载fat文件DiskGenius 磁盘取证例题[RCTF2019]disk 磁盘[](https://ciphersaw.me/ctf-wiki/misc/disk-memory/introduction/#_2)内存取证工具volatility 内存取证例题数字取证赛题0x01.从内存中获取到用户admin的密码并且破解密码 …

LangChain手记 Overview

整理并翻译自DeepLearning.AILangChain的官方课程:Overview 综述(Overview) LangChain是为大模型应用开发设计的开源框架 LangChain目前提供Python和JavaScript(TypeScript)两种语言的包 LangChain的主攻方向是聚合和…

使用docker部署一个jar项目

简介: 通过docker镜像, docker可以在服务器上运行包含项目所需运行环境的docker容器, 在线仓库里有很多各个软件公司官方发布的镜像, 或者第三方的镜像. 如果我们需要使用docker把我们的应用程序打包成镜像, 别的机器上只要安装了docker, 就可以直接运行镜像, 而不需要再安装应…

基于ChatYuan-large-v2 语言模型 Fine-tuning 微调训练 广告生成 任务

一、ChatYuan-large-v2 ChatYuan-large-v2是一个开源的支持中英双语的功能型对话语言大模型,与其他 LLM 不同的是模型十分轻量化,并且在轻量化的同时效果相对还不错,仅仅通过0.7B参数量就可以实现10B模型的基础效果,正是其如此的…

VBA技术资料MF40:VBA_计数筛选状态的数据行数

【分享成果,随喜正能量】人唯有与喜欢的事物发展关系,不管是人或者是物还是事,包括喜欢自己外表、个性的部分,喜欢自己做的事,喜欢自己的创造,喜欢的风景……才给人带来对自己的认同。在与喜欢的事物互动关…

【Linux命令详解 | cd命令】Linux系统中用于更改当前工作目录的命令

文章标题 简介一,参数列表二,使用介绍1. 使用cd命令切换到特定目录2. 使用cd命令与路径相关的特殊字符3. 使用cd命令切换到包含空格的目录4. 使用cd命令切换到前一个和后一个目录5. 使用cd命令切换到用户的主目录6. 使用cd命令与绝对路径和相对路径 总结…