Mysql事务

一、事务存在的意义

1、事务定义

  • 事务:事务是一个最小的不可在分的工作单元;通常一个事务对应一个完整的业务(例如银行账户转账业务,该业务是一个最小的工作单元)
  • 一个完整的业务需要批量的DML(insert、update、delete)语句共同联合完成。
  • 事务只和DML语句有关,或者说DML语句才有事务。这个和业务逻辑有关,业务逻辑不同,DML语句的个数不同。

2.事务是什么?

多个操作同时进行,那么同时成功,那么同时失败。这就是事务。

事务有四个特性:一致性、持久性、原子性、隔离性

比如有一个订单业务

1.订单表当中添加一条记录 2.商品数量数据更新(减少) 3…

当多个任务同时进行操作的时候,这些任务只能同时成功,或者同时失败。

3.Mybatis关于事务的管理

MyBatis框架中的事务默认是手动提交的,也就是每次编写程序都需要调用commit()方法提交事务

<transactionManager type="JDBC"></transactionManager>  ====》程序员自己控制处理的提交和回滚

在这里插入图片描述

在这里插入图片描述

二、事务的四大性质

  1. 原子性:事务是一个不可分割的工作单位,要么同时成功,要么同时失败。例:当两个人发起转账业务时,如果A转账发起,而B因为一些原因不能成功接受,事务最终将不会提交,则A和B的请求最终不会成功。

  2. 持久性:一旦事务提交,他对数据库的改变就是永久的。:只要提交了事务,将会对数据库的数据进行永久性刷新。

  3. 隔离性:多个事务之间相互隔离的,互不干扰

  4. 一致性:事务执行接收之后,数据库完整性不被破坏

    注意:只有当前三条性质都满足了,才能保证事务的一致性

在这里插入图片描述

刷脏:Mysql为了保证存储效率,于是每次将要读写的文件是先存储在缓存池中,对于数据的操作是在缓存池中,而mysql将会定期的刷新到磁盘中。

1、如何保证原子性:

​ 首先:对于A和B两操作要操作成功就一定需要更改到表的信息,如果如图所示A语句操作成功,而B语句操作时出现断电等其他情况终止了操作,所以此时两个事务没有操作成功,在没有提交事务之前,mysql会先记录跟新前的数据到undo log日志里面,当最终的因为操作不成功而发生事务回滚时,会从undo log日志里面先前存好的数据,重新对数据库的数据进行数据的回退。

undo log日志:(撤销回退的日志)主要存储数据库更新之前的数据,用于作备份

2、如何保证事务的持久性:

通过重做日志:redo log日志,对于用户将对发生了修改而为提交的数据存入了redo log日志中,当此时发生断电等其他异常时,可以根据redo log日志重新对数据做一个提交,做一个恢复。

在这里插入图片描述

3、隔离性:

1事务的并发问题:

1、脏读(读未提交)

在这里插入图片描述

(1)、脏读:事务A读取到了事务已经修改但未提交的数据,这种数据就叫脏数据,是不正确的

2、读已提交:(不可重复读)

在这里插入图片描述

不可重复读:对于事务A多次读取同一个数据时,由于其他是事务也在访问这个数据,进行修改且提交,对于事务A,读取同一个数据时,有可能导致数据不一致,叫不可重复读

3、可重复读:(幻读)

在这里插入图片描述

幻读:原因:因为mysql数据库读取数据时,是将数据放入缓存中,当事务B对数据库进行操作:例如删除所有数据且提交时,事务A同样能访问到数据,这就产生了幻读。
问题:解决了可重复读,但是会产生一种问题,错误的读取数据,对于其他事务添加的数据也将访问不到

4、串行化

在这里插入图片描述

串行化:事务A和事务B同时访问时,在事务A修改了数据,而没有提交数据时,此时事务B想增加或修改数据时,只能等待事务A的提交,事务B才能够执行。

**问题:**用户的体验十分的差,因为每次访问时都要等待其他事务的提交才能操作

伴随着对应的解决方案:

2事务的隔离等级:

隔离性的隔离级别

  1. 读未提交 read uncommitted
  2. 读已提交 read committed
  3. 可重复读 repeatable read
  4. 串行化 serializable

(1)、读未提交:事物A和事物B,事物A未提交的数据,事物B可以读取到。 这种隔离级别最低,这种级别一般是在理论上存在,数据库隔离级别一般都高于该级别。 三种并发问题都没解决。

set global transaction isolation level read uncommitted;
#查看当前隔离级别
select @@global.tx_isolation,@@tx_isolation;

(2)、读已提交:事务A只能读取到事务B提交的数据,这种级别可以避免“脏数据” ,这种隔离级别会导致“不可重复读取” ,Oracle默认隔离级别

set global transaction isolation level read committed;
查看当前隔离级别
select @@global.tx_isolation,@@tx_isolation;

(3)、可重复读:- 事务A和事务B,事务A提交之后的数据,事务B读取不到 - 事务B是可重复读取数据 - 这种隔离级别高于读已提交 - 换句话说,对方提交之后的数据,我还是读取不到 - 这种隔离级别可以避免“不可重复读取”,达到可重复读取 - 比如1点和2点读到数据是同一个 - MySQL默认级别 - 虽然可以达到可重复读取,但是会导致“幻像读”

set global transaction isolation level repeatable read;
查看当前隔离级别
select @@global.tx_isolation,@@tx_isolation;

(4)、串行化:事务A和事务B,事务A在操作数据库时,事务B只能排队等待 这种隔离级别很少使用,吞吐量太低,用户体验差 这种级别可以避免“幻像读”,每一次读取的都是数据库中真实存在数据,事务A与事务B串行, 而不并发

set global transaction isolation level serializable;

查看当前隔离级别
select @@global.tx_isolation,@@tx_isolation;

3隔离级别的一致性的关系:

在这里插入图片描述

三、事务的相关技术代码

  • 开启事务:START TRANSACTION
  • 事务的提交:COMMIT
    ages/image-20220605111202527.png" alt=“image-20220605111202527” style=“zoom:80%;” />

三、事务的相关技术代码

  • 开启事务:START TRANSACTION
  • 事务的提交:COMMIT
  • 事务的回滚:ROLLBACK (一旦事务提交失败,我们需要将数据回滚到之前的状态,需要用到rollback语句)
Logo

更多推荐