事务的概念
事务指逻辑上的一组操作,组成这组操作的各个单元,要不全部成功,要不全部不成功,主要用来保证数据的完整性和一致性。
提交事务:将此事务对数据库数据的操作(新增、删除、更新)永久的记录到数据库中。
回滚事务:将此事务对数据库数据的操作(新增、删除、更新)撤回,恢复到事务处理之前的状态。
事务是逻辑上的一个程序执行单元,用来保证数据的完整性和一致性。但有些数据库不支持事务,任何支持事务的数据库,都必须具备4个特性:
- 原子性(Atomicity)
- 一致性(Consistency)
- 隔离性(Isolation)
- 持久性(Durability)
也就是我们常说的事务ACID,这样才能保证事务(Transaction)中数据的正确性。
1)原子性:原子性是指事务包含的所有操作要么全部成功提交,要么全部失败回滚。
2)一致性:一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。
3)隔离性:隔离性是多个并发的事务同时访问一个数据库时,一个事务不应该被另一个事务所干扰,多个并发事务之间要相互隔离。 关于事务的隔离性数据库提供了多种隔离级别。
4)持久性:持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
事务的隔离性
当多个线程都开启事务操作数据库中的数据时,数据库系统要能对事务进行隔离操作,以保证各个线程获取数据的准确性。在介绍数据库提供的各种隔离级别之前,先看看如果不考虑事务的隔离性,会发生的几种问题:
1,脏读:脏读是指在一个事务处理过程里读取了另一个未提交的事务中的数据,若未提交的事务进行回滚,则前一个事务读到的就是脏数据。
2,不可重复读:一个事务中多次进行数据读取时,每次读取到的数据可能不一致。比如事务1和事务2同时操作同一个数据,事务1第一次时读到了原始数据,此时事务2更新了数据并提交了事务,事务1再次读取时,读取了最新数据。这样事务1两次读取的数据不一致。
3,幻读:和不可重复读类似。一个事务多次读取时读到了其他事务插入的数据,造成了前后读取的数据量不一致。因为无法阻止其它事务插入或删除,无法保证每次读取的行数量一致。
不可重复读和幻读的区别:不可重复读针对的是某数据值的不同(更新),幻读指的是数据条数的不同(新增或删除)。
事务隔离级别
在数据库操作中,为了有效保证并发读取数据的正确性,提出的事务隔离级别,数据库共定义了四种隔离级别,由低到高依次为:
1)Read uncommitted (可读取未提交内容)
2)Read committed (读取提交内容)
3)Repeatable read (可重读)
4)Serializable(串行化)
这四个级别可以逐个解决脏读、不可重复读、幻读这几类问题。
第1级别:Read Uncommitted(读取未提交内容)
该级别下所有事务都可以读取其他未提交事务的更新结果。
第2级别:Read Committed(读取提交内容)
该级别下一个事务只能看见已经提交事务所做的改变。可以避免脏读,但无法避免不可重复读和幻读。
第3级别:Repeatable read (可重读)
该级别可以保证一个事务对同一笔数据的读取结果始终相同。可以避免脏读和不可重复度,但无法避免幻读。
第4级别:Serializable(串行化)
最为严格的隔离级别,所有的事务操作都必须依次顺序执行,可以避免其他隔离级别遇到的所有问题,是最为安全的隔离级别, 但同时也是性能最差的隔离级别,因为所有的事务在该隔离级别下都需要依次顺序执行,所以,并发度下降,吞吐量上不去,性能自然就下来了。
四种隔离级别最高的是Serializable级别,最低的是Read uncommitted级别,级别越高,执行效率就越低。像Serializable这样的级别,就是以锁表的方式(类似于Java多线程中的锁)使得其他的线程只能在锁外等待,所以平时选用何种隔离级别应该根据实际情况。
在MySQL数据库中,支持上面四种隔离级别,默认的为Repeatable read (可重复读);
而在Oracle数据库中,只支持Serializable (串行化)级别和Read committed (读已提交)这两种级别,其中默认的为Read committed级别。
数据库的隔离级别是通过使用共享锁和排他锁实现的。具体见下篇文章。