【MySQL】事务

事务

  • 为什么使用事务
  • 概念
  • 使用
    • 回滚操作如何实现
    • 事务的基本特性
      • 事务之间的相互影响
        • 脏读
        • 不可重复读
        • 幻读
      • 隔离级别

为什么使用事务

想象一个场景
银行转账从一个账户A转到账户B200元,这个过程在数据库层面就是账户A的钱减少200,账户B的钱增加200
但是如果在转账的过程中,数据库服务崩溃,那么可能会出现A账户上的钱已经减少了,但是B账户的钱却没有增加,此时明显不符合要求.

为了解决这种问题,就提出了事务的概念

概念

事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部失败。
在不同的环境中,都可以有事务。对应在数据库中,就是数据库事务。

使用

  1. 开启事务
start transaction;
  1. 要执行的多条sql语句

  2. 回滚或者提交 (rollback/commit)
    rollback对应全部失败的情况 commit对应全部成功的情况

回滚操作如何实现

rollback对应的一个都不执行 不是真的没有执行 执行成不成功只有执行力才知道
那么回滚是如何实现的?
通过特定的日志来记录数据库事务操作的中间过程 如果需要回滚,就按照之前操作的"逆过程"来执行即可达到目的

插入对应的逆过程为删除
删除对应的逆过程为插入
修改对应的逆操作为改回去

因为是通过日志来记录事务执行的中间过程的,日志中的数据始终实在硬盘上存在的
即使数据库重启,也会在重启之后,针对没有回滚完的数据继续进行处理

事务的基本特性

  1. 原子性: 保证多个操作被打包成一个整体,要么全部执行成功,要么全都不执行
  2. 一致性: 事务执行之前和事务执行之后,数据要符合逻辑(通过约束和回滚机制来实现)
  3. 持久性:事务这里执行的各种操作,都是持久生效的(最终写入到硬盘中),一旦事务执行成功这楼里所有的操作产生的修改,都是写到硬盘中的
  4. 隔离性并发执行事务的时候,隔离性会在执行效率数据可靠之间做出权衡,隔离性描述的是同时执行的事务之间,相互产生的影响,隔离性越高,并发性就越底,数据就越可靠,性能就越低.

事务之间的相互影响

事务之间的相互影响分为几种,分别为:脏读不可重复读幻读

脏读

举个例子

假设有两个用户:Alice和Bob,他们分别有自己的银行账户。

现在,Alice正在执行一个事务,她想要转账给Bob 500元:

开始事务。
从Alice的账户中扣除500元。
暂停事务。

同时,Bob也在执行一个事务,他想要查询自己的账户余额:

开始事务。
读取Bob的账户余额,得到结果为1000元。
暂停事务。

接下来,Alice继续执行她的事务:

继续事务。
将500元转账给Bob。
提交事务。

最后,Bob继续执行他的事务:

继续事务。
提交事务。

在这个例子中,Bob发生了脏读。当Bob进行查询并读取自己的账户余额时,他读取到了未提交的数据,即尚未更新的余额,导致他看到的余额仍然是旧的余额,即使实际上已经收到了Alice转账的500元。

此时Bob读取到的1000元这个数据是一个临时的数据,并不是最终的数据 这种数据叫做 脏数据

那么这种情况如何解决呢?
答案是给’写’操作加锁,一个事务A在写的时候,其他事务就不可以进行读操作,知道事务A写完数据,提交数据,其他事务才能来读取数据

引入了给写操作加锁,降低了两个事务之间的并发性,提高了隔离性
降低了效率,但是使数据更加准确了

不可重复读

举个例子
假设有两个用户:Alice和Bob,他们的银行账户中有相同的初始余额1000元。

现在,Alice正在执行一个事务,她想要查询Bob的账户余额,并稍后再次查询

开始事务。
读取Bob的账户余额,得到结果为1000元。
暂停事务。

与此同时,Bob也在执行一个事务,他想要将自己的账户余额增加500元:

开始事务。
读取Bob的账户余额,得到结果为1000元。
将Bob的账户余额增加500元,计算得到新的余额为1500元。
提交事务。

随后,Alice继续执行她的事务:

继续事务。
读取Bob的账户余额,此时发生不可重复读,她读取到的余额是修改后的值,即1500元。
提交事务。

在这个例子中**,Alice在同一个事务中进行了两次读取操作,但第二次读取的结果发生了变化,导致不一致的情况。即Alice进行第一次读取时,Bob的事务尚未提交,所以读取到的余额是1000元;但在第二次读取时,Bob的事务已经提交,余额被更新为1500元,导致不可重复读的问题。**

Alice在一次事务的两次查询中结果却不相同,这就是产生了不可重复读的现象

那么这种情况该如何解决呢?

解决方法事故给读操作也加锁
给读操作加锁的意思,就是我在读取操作了时候,其他事务不能够修改正在读的这个表的数据

此时并发程度进一步降低了,不仅给写操作加锁,也给读操作加锁,隔离性进一步提高了,执行小效率降低了,数据的可靠性更高了

幻读

举个例子
假设有两个用户:Alice和Bob,他们正在执行交易。

Alice开始一个事务。

在事务中,她查询了一个范围条件的数据集合,例如“所有账户余额大于1000元的用户”。

Bob同时也开始了一个事务

并在此期间插入了一个满足范围条件的新记录。

Alice再次查询相同的范围条件的数据集合,但这次发现多了一条记录,即发生了幻读。

幻读的关键点是,在同一事务中,Alice执行了两次相同的查询,但结果集却不一致。这是因为在这期间,Bob的事务插入了一个新的记录,导致在第二次查询时,结果集增加了一条记录,就好像有幻觉一样。

那么这种情况如何解决呢?
解决幻读,办法只有一个,那就是串行化,彻底放弃并发执行事务,所有的事务都是一个挨着一个的串行执行
串行执行,并发性最低,隔离性最高,效率最低,数据最可靠

隔离级别

面对上述三种事务间的关系,MySQL数据库提供了四种事务的隔离级别
read uncommitted,read committed,repeatable read,serizlizable 对应三种关系

如图所示
【MySQL】事务_第1张图片

【MySQL】事务_第2张图片
并发程度不断降低,隔离程度不断提高,执行效率不断降低,数据可靠度不断提升

你可能感兴趣的:(MySQL,mysql,oracle,数据库)