目录
一、什么是事务
1.1事务的概念
事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部失败。
在不同的环境中,都可以有事务。对应在数据库中,就是数据库事务。
1.2为什么使用事务
数据库将数据有条理的存放在磁盘上,支持数据的增删改查,并在过程中保障数据的正确和可靠。但想要做到这点并不容易。
举一个例子就是银行转账,A账户给B账户转账2000交易的过程中, 就会出现几个问题:
- 怎么保证在A账户减少1000的同时B账户增加1000?
- 如何保证在大量交易的同时, 数据仍是合法的, 钱没有凭空产生或消失?
- 如果交易完成时, 数据库恰好崩溃, 那么如何保证交易数据成功保存在数据库中?
- A账户如果同时在和C账户交易, 如何让这两笔交易互不影响?
要保证交易的正常进行,数据库就要解决以上的问题,这就是事物诞生的原因。
二、事务的特性
2.1 事务的原子性
事务的的原子性是:将多个操作打包成一个操作,要么全部执行成功,要么全部执行失败,不存在部分执行成功,部分执行失败
回滚(rollback):
当转账汇款的时候,突然机器出现故障,有些操作可能已经执行了一部分了,但是不能继续执行了,这里就需要将执行的部分操作进行还原,也就是这里说的回滚(rollback)
回滚如何实现?
通过日志将事务中执行的每个操作都记录下来,如果需要回滚就通过将之前记录的操作进行逆操作来执行。
例如:上个操作是删除,逆操作就是插入
2.2 事务的一致性
一致性是指事务执行结束后, 数据库的完整性约束没有被破坏, 事务执行的前后都是合法的数据状态。例如:a转账给b 2000元,b不能收到3000
如何保证数据的一致性?一是通过约束; 二是通过回滚
2.3 事务的持久性
事务这里执行的各种操作都是,都是持久生效的(最终写入到硬盘的)一旦事务执行成功,这里的所有操作产生的修改,都是写到硬盘的。
2.4 事务的隔离性
隔离性是指,事物内部的操作与其他事务是隔离的,并发执行的各个事物之间不能互相干扰。隔离性越高,并发性越低,数据越可靠,性能越低.
并发执行事务,也就是同时执行多个事务,"同时"是指在宏观上是同时的,但是微观上还是有先有后的。当存在先后顺序的时候事务就会产生执行结果的不同,可能会出现数据的脏读、不可重复读和幻读。开发的过程中通常使用锁机制来保证事物的隔离性。
脏读:
事务A正在访问并修改数据,事务B读到了A未提交的数据(脏数据),这种现象就是脏读。通过脏读读到脏数据是临时的, 不是最终准确的数据。(并不是说这个数据是脏的)
时间 | A事务 | B事务 |
---|---|---|
T1 | 开始事务 | 开始事务 |
T2 | 将余额由1000改成3000 | |
T3 | 读取余额, 结果为3000[脏读] | |
T4 | 情况发生变化,将余额由1000改成5000 | |
T5 | 提交事务,最终的余额为5000 | 提交事物,查询到的结果为3000 |
如何解决脏读的问题?在事务A过程中加上锁,只有当事务A完成时,事务B才能对其进行操作。这样的情况下会降低两个事务的并发性,但是可以提高隔离性让数据更加准确。
不可重复读:
在事务A中先后读取同一个数据,事务A在第一次提交之后可能会再次对数据进行修改,而事务B只读取到了A第一次提交的结果,导致两次读取的数据不一样,这种现象就叫不可重复读。
如何解决不可重复读的问题?在事务B读取数据的过程中也加锁,只能等事务B读取完成事务A才能进行操作,这样会进一步导致并发程度进一步降低,但是隔离性提高数据更加准确。
幻读(不可重复读的特殊情况):
在事务A中读取数据,事务A在第一次提交之后去创建新的数据,而事务B只读取到了A第一次提交的数据集,没有读取到新的数据集,这种现象就叫幻读。
如何解决幻读?办法只有一个:串行化,彻底放弃并发执行事务,所有的事务依次执行。
2.5 MySQL中隔离级别
MySQL隔离级别有4个,由低到高分别为Read Uncommitted(允许读未提交的数据),Read Committed(允许读已提交的数据),Repeatable Read(可以重复读) ,Serializable(串行化)
隔离级别 | 脏读 | 不可重复读 | 幻读 |
Read Uncommitted(RU) | ✔️ | ✔️ | ✔️ |
Read Committed(RC) | ✖️ | ✔️ | ✔️ |
Repeatable Read(RR) | ✖️ | ✖️ | ✔️ |
Serializable | ✖️ | ✖️ | ✖️ |
MySQL中默认使用的是 Repeatable Read。
三、事务的使用
开启事务
start transaction;
提交事务:
commit;//全部执行
回滚:
rollback;//全不执行
一个事物必须要以commit或者rollback结尾,否则接下来的操作都会被认为是事务的一部分。