数据库事务:单个逻辑工作单元执行的一系列操作,这些操作要么完全地执行,要么完全地不执行。
事务的四大特性(ACID):原子性、一致性、隔离性、持久性。
原子性:事务包含的全部操作要么全部执行成功,要么全部失败回滚。
一致性:事务前后,数据库的状态都满足所有完整性约束。
隔离性:多个事务并发执行时,一个事务的执行不影响另一个事务的执行。
持久性:当事务完成以后,该事务对数据库的更改持久的保存在数据库中,并不会被回滚。
并发事务引起的问题:
1. 更新丢失:两个事务都同时更新一行数据,但是第二个事务却中途失败退出,导致对数据的两个修改都失效了。这是因为系统没有执行任何的锁操作,因此并发事务并没有被隔离开来。
2. 脏读:一个事务读取另一个事务还没有提交的数据。脏读又称无效数据读出。比如:事务T1修改了一行数据,但是还没有提交,这时候事务T2读取了被事务T1修改后的数据,之后事务T1因为某种原因Rollback了,那么事务T2读取的数据就是脏的。
3. 不可重复读:在相同的事务内两个相同的查询,返回了不同的结果。例如:事务T1读取某一数据,事务T2读取并修改了该数据,T1为了对读取值进行检验而再次读取该数据,便得到了不同的结果。
4. 幻读:事务在操作过程中进行两次查询,第二次查询出现了第一次查询没出现的内容或者缺少了第一次查询出现的数据。例如:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样。这就叫幻读。
事务的隔离级别:
更新丢失、脏读、不可重复读、幻读都和事务的隔离级别有关。通过设置事务的隔离级别,可以避免以上情况发生。
1. 未授权读取级别:也称为读未提交。以操作同一行数据为前提,读事务允许其他读事务和写事务,未提交的写事务禁止其他写事务(但允许其他读事务)。此隔离级别可以防止更新丢失,但不能防止脏读、不可重复读、幻读。此隔离级别可以通过“排他写锁”实现。
2. 授权读取级别:也称为读提交(Read Committed)。以操作同一行数据为前提,读事务允许其他读事务和写事务,未提交的写事务禁止其他读事务和写事务。此隔离级别可以防止更新丢失、脏读,但不能防止不可重复读、幻读。此隔离级别可以通过“瞬间共享读锁”和“排他写锁”实现。
3. 可重复读取级别:可重复读取(Repeatable Read)。
以操作同一行数据为前提,读事务禁止其他写事务(但允许其他读事务),未提交的写事务禁止其他读事务和写事务。此隔离级别可以防止更新丢失、脏读、不可重复读,但不能防止幻读。此隔离级别可以通过“共享读锁”和“排他写锁”实现。
4. 序列化级别:序列化(Serializable)。提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,不能并发执行。此隔离级别可以防止更新丢失、脏读、不可重复读、幻读。如果仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。
隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为Read Committed。它能够避免更新丢失、脏读,而且具有较好的并发性能。尽管它会导致不可重复读、幻读这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。