昨天去银行转钱,最后怒失300万

news2024/9/24 1:16:30

**本文首发于公众号【看点代码再上班】,建议关注公众号,及时阅读最新文章。**

原文:昨天去银行转钱,最后怒失300万

大家好,我是Eric,这是我的第24篇原创文章

我的300万"不见"了

小埃年初的时候看中了一套1000万的房子,需要首付300万,小埃暂时没钱然后向朋友小克借了300万,小克借了,小埃房子也买下了。

过去了半年,现在小埃有钱了,要还给小克。小埃说我不提现了,直接去银行转账吧,小克也觉得转账方便欣然答应。

那么,小埃转账过程银行系统应该要有以下几个步骤:

  1. 检查小埃账户里面余额至少有300万。

  2. 从小埃账户余额中扣减300万。

  3. 给小克账户余额增加300万。

这三个步骤涉及到两次MySQL操作,一次扣减,一次增加。如果执行完步骤2,MySQL突然宕机了,那就会出现一个“灵异”事件,小埃钱少了300万,但小克账户并未收到300万,小埃没有还钱成功,钱不翼而飞了!

要解决这种“灵异”事件,就必须把上面三个步骤打包成一个事务,任何一个步骤失败,则必须回滚所有的步骤到最开始的状态。

事务(Transaction),它是并发控制的基本单位,它可以由一条简单的SQL语句组成,也可以由多条SQL语句构成,但不管如何,一个事务中的SQL语句要么都执行成功,要么都失败,他们是不可分割的。

手动开启一个MySQL事务

首先,我们平常写SQL语句基本没有“明面上接触”过事务,我们大多数基本也没有手动开启过一个事务,但是我们的SQL都运行在事务之上。

这是因为我们MySQL默认是事务自动提交的,比如我们连接MySQL,通过select @@autocommit语句或者show variables like 'autocommit'语句查看是否开启事务自动提交。

1表示开启自动提交,0表示关闭自动提交。

ON表示开启自动提交,OFF表示关闭自动提交。

我们可以通过set autocommit = 0语句改变自动提交的模式。

比如我们现在有一张表bank_balance,保存了小埃和小克的账户余额,现在小埃账号余额300万,小克账号余额0:

通过set autocommit = 0关闭事务自动提交。

mysql> set autocommit = 0;Query OK, 0 rows affected (0.00 sec)mysql> show variables like 'autocommit';+---------------+-------+| Variable_name | Value |+---------------+-------+| autocommit    | OFF   |+---------------+-------+1 row in set (0.01 sec)update bank_balance set balance = balance - 300000000 where user_name = '小埃';Query OK, 1 row affected (0.01 sec)Rows matched: 1  Changed: 1  Warnings: 0mysql> commit;Query OK, 0 rows affected (0.00 sec)

以上流程通过开启两个cmd窗口看起来最直观,左边窗口select,右边窗口update。

如下视频,当右边窗口update而未commit前,左边窗口select看不到更新后的数据:

事务的特征都有哪些?

市面上的MySQL存储引擎很多,比如MyISAM,NDB Cluster,Maria,Memory等。MyISAM是MySQL5.5.8版本以前的默认存储引擎,但MyISAM不支持事务,至于MyISAM不支持事务的原因以后有机会写一篇哈哈~

数据库事务是在引擎层实现的,我们常见的支持事务的引擎有InnoDB,所以InnoDB也是目前MySQL用的最多的引擎。

事务有四大基本特征,简称ACID特性:

A(Atomicity),原子性原子性指整个数据库事务是不可分割的工作单位,要么全部操作完成,要么全部操作不完成,才算整个事务成功。如果事务中有任何一段SQL语句执行失败,那么在此之前已经执行的SQL语句必须回滚,也即数据库状态必须退回到执行事务前的状态。

C(Consistency),一致性:一致性是指事务将数据库从一种状态转变成为下一种状态时,数据库的完整性约束不会被破坏。比如现在有一个事务有两个SQL语句操作表中的一个字段user_name,而user_name字段有唯一键约束,事务如下:

begin;update table  set user_name = '小埃' where user_name = '小克';insert into table(user_name)values('小埃');commit;

这个事务会导致表中的user_name字段变得不唯一,这就破坏了事务的一致性要求,即事务将数据库从一种状态变为了一种不一致的状态,这时系统会自动撤销事务(返回初始的状态)。

l(Isolation),隔离性:事务的隔离性代表着每个事务之间相互分离,事务A的操作在提交前对事务B不可见。这个特性可以让多个事务多步骤交替执行时数据的最终一致性得到保障。

D(Durability),持久性:持久性表示事务一旦提交,其对数据的修改就是永久性的。即使发生数据库宕机,只要磁盘没坏,数据库也能把数据恢复到宕机前的状态。

丢失的300万"回来"了

有了以上四大特征作为标准保障,当我们把小埃还钱300万这个事情打包成一个事务的话:

      事务开始

  1. 检查小埃账户里面余额至少有300万。

  2. 从小埃账户余额中扣减300万。

  3. 给小克账户余额增加300万。

    提交事务

如果在执行完第2步而未执行第3步的时候,MySQL宕机了,那么MySQL它是如何保障小埃的300万还在,且小克账户余额也没有多300万的?

其实,MySQL为了实现事务,需要并发控制和恢复机制,这两玩意说白了就是在修改确认(commit)前不让别人看到我修改的东西,以及未来得及确认前可以把数据恢复到修改前的状态。

这就涉及到MySQL的MVCC(多版本并发控制)、Read View(读视图)、redo log(重做日志)等等。

先来看一个事务的大概流程:

(ps:事务是两阶段提交,严谨地说更新数据前有一个prepare  redo log阶段)

MVCC和Read View一起实现了事务的隔离性,即一个事务数据更新而未提交前,其他事务查询不到该事务更新的数据值。

redo log是一个很关键的东西(以后再专门抽一讲来说),存在于InnoDB存储引擎中,我们现在先不用太过于纠结它的底层实现,只要知道它记录了事务的数据状态,也即是数据更新之后的值,MySQL宕机重启时数据恢复也基于redo log。

回到问题本身,以上所讲“执行完第2步而未执行第3步的时候,MySQL宕机了” 主要说是发生在更新数据这个环节,当然也可能在数据更新完之后、写入redo log时或写入redo log后MySQL宕机。

由于事务的隔离性,此时MySQL宕机,更新的数据其实其他"用户"查询不到,小埃账户扣减300万后,不管小埃本人还是小克等其他人查询小埃账户余额依然是300万!

当MySQL重启的时候,系统会做crash recovery,即是根据redo log中记录的日志和MySQL的数据值来决定未提交的事务是继续提交还是回滚,如果提交一定是小埃和小克账号余额同时加减300万成功,如果回滚则什么都没发生。

“执行完第2步而未执行第3步的时候,MySQL宕机了” ,在InnoDB引擎中的表象是:redo log仍未写入但MySQL已有数据,重启时系统会把事务提交,最终看到的是小埃还款成功。

积土成山,非斯须之作,贵在坚持而非积土。

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

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

相关文章

将grub安装到u盘

安装grub sudo apt-get install grub查看磁盘信息 fdisk -lu盘设备是/dev/sdb 使用fdisk编辑磁盘 fdisk /dev/sdbd命令删除磁盘分区 n命令新建磁盘分区 a命令将分区激活 w命令将更改保存到磁盘 创建两个分区,将其中一个设置活动分区。用于安装grub。剩下的分区可…

【源码解读】扩散模型核心:DDPM专题-结合源码讲解

目录 1. 训练1.1 Uniform({1,...,T})1.2 ϵ ∼ N ( 0 , I ) \boldsymbol{\epsilon} \sim \mathcal{N}(\mathbf{0}, \mathbf{I}) ϵ∼N(0,I)1.3 加噪1.4 加噪图片送入UNet预测加入的噪声1.5 预测的噪声和加入的噪声进行损失计算 2. 采样3. 推理 本次训练采用的是cifar数据集&am…

15天涨粉50万!B站有900万人看过都说“震撼”

“卷”是内容创作者对现在互联网竞争最大的评价,创作者之间复制力极强,导致赛道竞争力大,创作者亟待不断地推动自己找到一个又一个新的内容差异、流量风口。 所以不管是创作者还是品牌,只要是涉及到内容运营的都只有一个目标&…

【C#】反射机制,动态加载类文件

系列文章 【C#】编号生成器(定义单号规则、固定字符、流水号、业务单号) 本文链接:https://blog.csdn.net/youcheng_ge/article/details/129129787 【C#】日期范围生成器(开始日期、结束日期) 本文链接:h…

网络解析----yolov3网络解析

Yolov3是一种针对目标检测任务的神经网络模型,其网络结构主要由三个部分组成:特征提取网络、检测头和非极大值抑制(NMS)模块。特征提取网络采用Darknet-53作为骨干网络,Darknet-53由53个卷积层和5个Max-Pooling层组成&…

死锁的产生

死锁的产生:有一个公共区的玩具,A和B想玩,但是A先得到了玩具,A玩完玩具之后又去干别的事情,但是并没有把玩具还回去,此时B就玩不到了玩具,在无限期的等待。 如下图所示: 线程1把num资…

php压缩一个文件夹,php下载多个图片

$area_id 100;$area_name 一百;shell_exec("cd /www/wwwroot/api/public/images/ && zip -r " . $area_name . ".zip " . $area_id . "/"); 把 100/ 这个文件夹,压缩成 一百.zip 然后得到zip所在的下载url 这个功能&…

百度编辑器(Ueditor)视频上传到阿里云 + 预览不支持FLASH问题解决 + 输入框不展示视频播放页面问题解决

目前需求方提出的问题是以下四个: 1.百度编辑器(Ueditor)视频上传到阿里云 2.解决不支持FLASH问题 3.视频上传后可以预览 4.修改视频封面 看一下原始的功能是什么样的 上传视频: 视频上传完成 上传视频保存的路径&#xff1…

使用vant组件库

参考网址 Vant Weapp - 轻量、可靠的小程序 UI 组件库 1.在小程序中右键打开外部终端窗口 2.npm init -y 生成package.json 如果没有npm指令则需安装node.js 地址:https://nodejs.org/dist/v18.16.1/node-v18.16.1-x64.msi 3.npm i vant/weapp1.3.3 -S --pro…

PHP 论坛系统mysql数据库web结构apache计算机软件工程网页wamp

一、源码特点 PHP 论坛系统 是一套完善的web设计系统,对理解php编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为PHP APACHE,数据库为 mysql5.0,使用php语言开发。 下载链接…

oracle服务器的CPU占用率一直100%排查方式

背景说明 公司开发、测试、演示环境,三个环境的oracle服务器无论服务器是否空闲, CPU的占用率一直是100%, 一直也没有找到问题原因,今天就花了一整天时间研究这个问题。 通过AWR报告查看oracle运行情况 awr报告是oracle 10g下提…

一种人体属性识别的网络结构

0、前言 人体属性识别,是一个典型的多标签分类场景。每个人体有多个标签,如年龄、性别、衣着颜色等,而每个属性又有多种类别,如年龄分儿童青年老人、性别分男女、颜色分红绿青蓝紫... 本文提供了一个网络结构来执行这种任务。 …

【KVM】命令行安装kvm

命令行安装kvm 一、准备镜像文件 mkdir /home/iso cd /home/iso rz ls CentOS-7-x86_64-Minimal-2009.iso二、使用命令行安装虚拟机 virt-install --virt-typekvm --nameKVM_01 --vcpus4 --memory6000 --location/opt/CentOS-7-x86_64-Minimal-2009.iso --disk path/data/kv…

2021年全国硕士研究生入学统一考试管理类专业学位联考数学试题——纯题目版

2021 年 1 月份管综初数真题 一、问题求解(本大题共 5 小题,每小题 3 分,共 45 分)下列每题给出 5 个选项中,只有一个是符合要求的,请在答题卡上将所选择的字母涂黑。 1.某便利店第一天售出50种商品&…

联邦学习中的模型聚合

目录 联邦学习中的模型聚合 1.client-server 算法 2. fully decentralized(完全去中心化)算法 联邦学习中的模型聚合 在联邦学习的情景下引入了多任务学习,其采用的手段是使每个client/task节点的训练数据分布不同,从而使各任务节点学习到不同的模型…

[python] 进度条使用

from tqdm import tqdm# 创建一个示例字典 my_dict {a: 1, b: 2, c: 3}# 使用tqdm遍历字典的键 for key in tqdm(my_dict.keys()):# 在这里编写你的代码# 这部分代码将会在进度条中显示pass# 使用tqdm遍历字典的值 for value in tqdm(my_dict.values()):# 在这里编写你的代码#…

查看 git的 config 配置

git config --list // 查看全部配置信息git config user.name // 查看指定配置信息 查看某一个配置信息 git config --global user.email 参考 如何查看gitconfig配置_笔记大全_设计学院

牛客BM21 旋转数组的最小数字

描述 有一个长度为 n 的非降序数组,比如[1,2,3,4,5],将它进行旋转,即把一个数组最开始的若干个元素搬到数组的末尾,变成一个旋转数组,比如变成了[3,4,5,1,2],或者[4,5,1,2,3]这样的。请问,给定…

IDEA远程DeBug调试

1. 介绍 当我们在开发过程中遇到一些复杂的问题或需要对代码进行调试时,远程调试是一种非常有用的工具。使用 IntelliJ IDEA 进行远程调试可以让你在远程服务器上的应用程序中设置断点、查看变量和执行调试操作。 远程调试的好处如下: 提供更方便的调试…

大众汽车车载娱乐系统曝安全漏洞,可被远程控制

根据GitHub的一份报告,大众汽车Discover Media信息娱乐系统的漏洞是在2023年2月28日发现的。 该漏洞可能会使未打补丁的系统遭到拒绝服务(DoS)攻击。该漏洞起初是由大众汽车的用户发现的,随后大众汽车方面确认了该漏洞&#xff0…