数据库的事务、事务并发以及隔离级别

来源:互联网 发布:matlab读取数据和文件 编辑:程序博客网 时间:2024/05/01 13:19

一、事务的概念

事务的定义:

事务(Transaction)是并发控制的单位,是用户定义的一个操作序列。这些操作要么都做,要么都不做,是一个不可分割的工作单位。通过事务,SQL Server能将逻辑相关的一组操作绑定在一起,以便服务器保持数据的完整性。事务通常是以BEGIN TRANSACTION开始,以COMMIT或ROLLBACK结束。COMMIT表示提交,即提交事务的所有操作。具体地说就是将事务中所有对数据库的更新写回到磁盘上的物理数据库中去,事务正常结束。ROLLBACK表示回滚,即在事务运行的过程中发生了某种故障,事务不能继续进行,系统将事务中对数据库的所有以完成的操作全部撤消,滚回到事务开始的状态。

事务的四大特性(ACID特性):

  1. 原子性(Atomicity)事务是数据库的逻辑工作单位,事务中包括的诸操作要么全做,要么全不做。
  2. 一致性(Consistency)事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
  3. 隔离性(Isolation)一个事务的执行不能被其他事务干扰。
  4. 持续性/永久性(Durability)一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。

二、事务的并发

并发可以定义为多个进程在相同时间访问或者更改共享数据的能力。一般数据库为了提高性能,都允许多个客户端同时访问数据库,也就是说数据库中某个相同的数据在相同的时间段内同时有多个事务同时进行,这就是事务的并发。如果在事务并发时并没有采取相应的隔离措施,就很容易造成数据的丢失,破坏。

多个事务同时访问数据库时候,会发生下列5类问题,包括3类数据读问题,2类数据更新问题:

A:数据更新问题:

  1. 第一类丢失更新:A事务撤销时,把已经提交的B事务的更新数据覆盖了;
  2. 第二类丢失更新:A事务提交时覆盖了B事务提交的数据;

B:数据读问题

  1. 脏读(dirty read):A事务读取B事务尚未提交的更改数据,并在这个数据基础上操作。如果B事务回滚,那么A事务读到的数据根本不是合法的,称为脏读。在oracle中,由于有version控制,不会出现脏读;
  2. 不可重复读(unrepeatable read):A事务读取了B事务已经提交的更改(或删除)数据。比如A事务第一次读取数据,然后B事务更改该数据并提交,A事务再次读取数据,两次读取的数据不一样。;
  3. 幻读(phantom read):A事务读取了B事务已经提交的新增数据。注意和不可重复读的区别,这里是新增,不可重复读是更改(或删除)。这两种情况对策是不一样的,对于不可重复读,只需要采取行级锁防止该记录数据被更改或删除,然而对于幻读必须加表级锁,防止在这个表中新增一条数据。

三、事务的隔离级别

数据库事务的隔离级别有4个,由低到高依次为Read uncommitted、Read committed、Repeatable read、Serializable,这四个级别可以逐个解决脏读、不可重复读、幻读这几类问题。


  1.  Serializable (串行化): 添加范围锁(比如表锁,页锁等),直到transaction A结束。以此阻止其它transaction B对此范围内的insert,update等操作。幻读,脏读,不可重复读等问题都不会发生。
  2.  Repeatable read (可重复读): 对于读出的记录,添加共享锁直到transaction A结束。其它transaction B对这个记录的试图修改会一直等待直到transaction A结束。可能发生的问题:当执行一个范围查询时,可能会发生幻读。
  3.  Read committed (读已提交): 在transaction A中读取数据时对记录添加共享锁,但读取结束立即释放。其它transaction B对这个记录的试图修改会一直等待直到A中的读取过程结束,而不需要整个transaction A的结束。所以,在transaction A的不同阶段对同一记录的读取结果可能是不同的。可能发生的问题:不可重复读。
  4. Read uncommitted (读未提交): 不添加共享锁。所以其它transaction B可以在transaction A对记录的读取过程中修改同一记录,可能会导致A读取的数据是一个被破坏的或者说不完整不正确的数据。另外,在transaction A中可以读取到transaction B(未提交)中修改的数据。比如transaction B对R记录修改了,但未提交。此时,在transaction A中读取R记录,读出的是被B修改过的数据。可能发生的问题:脏读。




0 0