事务的四大特性
一般来说,事务是必须满足4个条件(ACID):原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。
原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
事务的并发问题
脏读:事务A读取了事务B更新的数据,然后事务B回滚,那么事务A读取到的数据就是脏数据
不可重复读:事务A多次读取同一数据,事务B在事务A多次读取的过程中对数据做了更新并提交,导致事务A多次读取同一数据的结果不一致,侧重于修改
幻读: 系统管理员A将数据库中所有的学生的成绩从具体分数改为ABCD等级,同时系统管理员B插入了或删除了一条具体分数的记录,导致A发现结束后还有一条数据没有改过来或是丢失了,就好像出现了幻觉一样
事务的隔离级别
读未提交(read-uncommitted),读提交(read-committed),可重复读(repeatable-read),串行化(serializable)
案例:
首先设置和查询数据库的隔离级别,如下
以下的几种设置方式相似。
1.读未提交(read-uncommitted)
结论:客户端A可以读取到客户端B修改后但未提交的数据,一旦客户端B的事务因为某种原因回滚,所有的操作都将会被撤销,那客户端A查询到的数据其实就是脏数据。
2.读提交(read-committed)
结论:客户端B的事务还没提交,客户端A不能查询到B已经更新的数据,解决了脏读问题,但是客户端A执行与上一步相同的查询,结果与上一步不一致,即产生了不可重复读的问题。
3.可重复读(repeatable-read)
解决了不可重复读的问题,但是看下图:
出现幻读问题。
结论:客户端A在查询过程中,客户端B有数据修改并提交事务,客户端A再查询和上一步结果相同,解决了不可重复读的问题,但是还会存在幻读的问题。比如客户端A查询时没有id为1的数据,此时客户端B向表中插入一条数据id为1并提交,这时客户端A任然以位数据库中没有id为1的数据,于是插入一条id为1的数据,结果报错了,就发生了幻读的问题。
串行化(serializable)
串行化利用加锁的方式,在这个事务没有被提交之前其他的线程,只能等到当前操作完成之后,才能进行操作,这样会非常耗时,而且,影响数据库的性能,通常情况下,不会使用这种隔离级别。但是这种方式解决了幻读的问题。