事务的四大特性
ACID:
- Atomicity:原子性,事务要么全部完成,要么回滚到执行前的状态;
- Consistency:一致性,写入数据满足约束条件。一致性作为目的,原子性、隔离性和持久性都是手段;
- Isolation:隔离性,事务之间应该是互不干扰的;
- Duration:持久性,事务在任何情况都能提交和回滚,就算服务器崩溃。
原子性
保证整个业务在一个事务之中
一致性
需要其他几个特性来实现,以保证数据库数据不会平白出现或者平白消失
隔离性
按照理论来说,事务之间是要完全隔离的。但是,完全隔离在实际情况下,效率太低,所以有以下几个隔离等级:
注意,下面所有提及的读,背景都是两个事务同时运行,一个做增删改,一个做读取,读取事务中有两次对同一个数据的读取,而增删改事务刚好在两次读取之间发生。
- 串行(SQLLite默认模式):就是按顺序执行事务,完全隔离,但是效率低。
- 可重复读(Mysql默认模式):当一个事务修改目标表并提交时,正好有另外一个事务在修改事务的前后对目标表数据进行了查询,两次查询的结果一样,叫做可重复读。可重复读只对修改数据有效,对新增无效,如果修改事务改为新增事务,那么查询事务的两次查询会得到不同结果,这叫幻读。
- 读已提交(Oracle、PostgreSQL、SQL Server默认模式):相对于可重复读,读已提交的隔离性更低,不仅新增事务两次查询的结果不一样,修改事务两次查询的结果也不一样。
- 读未提交:读未提交隔离性最低,在增删改事务对数据进行修改,但还未提交时,外部的线程就能察觉到数据的更改。在这种情况下,一旦增删改事务发生了回滚,那么查询事务第二次查询的结果就会出现脏读。
为什么要分上面四个级别,主要是性能和安全问题不可兼得,保证安全就要损失一定的性能,没有哪个最好,只有哪个最适合当前的项目。
那为什么不同级别的锁会对性能造成损失,主要是因为加锁的时间跨度和键值范围。
持久性
事务都对应实时日志,一旦服务崩溃,重启的时候可根据日志完成之前的事务,或者回滚。