一直在说,甚至在开发过程中使用spring时还经常使用transaction的注解,但一直没有仔细了解记忆过
什么是事务?
事务是一个完整的业务逻辑。
人话:是一个最小的工作单位,不能再分割了,而且他们要么成功,要么失败。
- 例如:转账的例子,一个减钱,一个加钱,必须同时成功或者失败,不能说只完成一半。
什么时候考虑事务
只要进行DML(增删改)语句操作才有事务的概念,而DQL(或者说查询,创建)之类的操作没有事务可言,因为他们并没有实际影响到数据库中数据!
但只要进行DML语句操作,就必须考虑事务,数据安全是最重要,最首先需要考虑的!
那么如果所有的业务都只需要调动一个DML语句就能实现,那还需要事务性么?
不需要了,sql语句天生具有原子性,一致性。(个人理解,不一定对)
但是实际上很少发生这种情况,多数情况下,业务都是需要多个sql语句配和完成。
所以事务就是多条DML语句要么同时成功,要么同时失败。
事务是怎么实现的呢?
首先我们要知道:mysql数据库默认使用InnoDB数据引擎*(5.5版本之后)。
- 而InnoDB数据引擎在你每次执行DML操作之后都会把DML语句保存到一个事务日志里。
事务:transaction
提交事务(commit):
- 清空事务日志,把数据操作结果持久化(保存硬盘)到数据库中。 代表着一次事务结束,全部成功的结束。
回滚事务(rollback):
- 撤销所有DML操作,清空事务日志。代表一次事务结束,全部失败的结束。
mysql默认的事务行为是什么?
自动提交:你操作一次DML他就给你提交一次。
关闭:star transaction
事务的特性
ACID
- 原子性:事务是最小单位,不可再分割。
- 一致性:要么多条DML操作同时成功,要么同时失败。
- 隔离性:事务与事务之间都会有一定的隔离(根据隔离级别)
- 持久性:提交后会把进行DML操作之后的结果保存到硬盘中。
隔离级别是什么
-
读未提交(最低隔离级别)(不提交也能读到)
事务A可以读到事务B未提交的数据。 那么势必会读到一些无用的,或者准备废弃的DML操作结果,这就是!脏读现象!(读到了不干净的数据)。 理论上的隔离级别,实际没人敢用,对于数据保护性太差。
-
读已提交(大多数数据库从这开始)(提交了才能读到)
事务A可以读取到事务B提交后的数据。解决了脏读,但是不可重复读取: 事务A第一次从事务B读取到数据为1条,但是事务B还没结束,第二次读取可能变成2条,前后不一致,所以不可重复读取。 但是每次读取到数据都是绝对真实。
-
可重复读(mysql默认级别)(提交了也不一定读的到)
事务A开启后读取事务B,且不管事务B期间提交事务没,在事务A的读取结果都是一开始的,从未改变。 解决了不可重复读,但是又发生了新的问题:幻读 因为读取的数据不是实时的,所以数据不够真实。 个人猜想:银行转账是用的这个么?甚至支付?我一旦开始支付,那么我在支付的过程中给账户充值,账户余额是不变的,只有我结束本次支付后,余额才改变。
-
序列化/串行化(最高的隔离级别)
通过让事务阻塞排队解决了以上所有问题,但是效率低,因为不能并发。 个人猜想:是否使用多线程技术中的互斥锁(悲观锁)。