Mysql事务
一、事务存在的意义
1、事务定义
- 事务:事务是一个最小的不可在分的工作单元;通常一个事务对应一个完整的业务(例如银行账户转账业务,该业务是一个最小的工作单元)
- 一个完整的业务需要批量的DML(insert、update、delete)语句共同联合完成。
- 事务只和DML语句有关,或者说DML语句才有事务。这个和业务逻辑有关,业务逻辑不同,DML语句的个数不同。
2.事务是什么?
多个操作同时进行,那么同时成功,那么同时失败。这就是事务。
事务有四个特性:一致性、持久性、原子性、隔离性
比如有一个订单业务
1.订单表当中添加一条记录 2.商品数量数据更新(减少) 3…
当多个任务同时进行操作的时候,这些任务只能同时成功,或者同时失败。
3.Mybatis关于事务的管理
MyBatis框架中的事务默认是手动提交的,也就是每次编写程序都需要调用commit()方法提交事务
<transactionManager type="JDBC"></transactionManager> ====》程序员自己控制处理的提交和回滚
二、事务的四大性质
-
原子性:事务是一个不可分割的工作单位,要么同时成功,要么同时失败。例:当两个人发起转账业务时,如果A转账发起,而B因为一些原因不能成功接受,事务最终将不会提交,则A和B的请求最终不会成功。
-
持久性:一旦事务提交,他对数据库的改变就是永久的。注:只要提交了事务,将会对数据库的数据进行永久性刷新。
-
隔离性:多个事务之间相互隔离的,互不干扰
-
一致性:事务执行接收之后,数据库完整性不被破坏
注意:只有当前三条性质都满足了,才能保证事务的一致性
刷脏: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事务的隔离等级:
隔离性的隔离级别
- 读未提交 read uncommitted
- 读已提交 read committed
- 可重复读 repeatable read
- 串行化 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语句)