标签:
在软件领域,全有或者全无的操作被称作事务(Trancatioin)。事务允许你将几个操作组合成一个要么全部发生要么全部不发生的工作单元。如果这几个操作都顺利,事务将会成功。但是如果出现有任何一个操作出错的话,所发生的行为将被清除干净(事务回滚)。
一、 事务的四个要素
1) 原子性(Atomic)
事务是由一个或多个活动组成的一个工作单元。原子性确保了事务中的所有操作全部发生或全部不发生。如果所有的活动都成功了,事务也就成功了。如果任意一个活动失败了,整个事务也失败并回滚。
2) 一致性(Consistent)
一旦事务完成,系统必须确保它所建模的业务除以一致状态。
3) 隔离性(Isolated)
事务允许多个用户对相同的数据进行操作,每个用户的操作不会与其他用户纠缠在一起。因此,事务应该被彼此隔离,避免发生同步读写相同数据的事情(注意的是,隔离性往往涉及到锁定数据库中的行或表)。
4)持久性(Durable)
一但事务完成,事务的结果应该持久化,这样就能从任何系统崩溃中恢复过来。这一般会涉及将结果存储到数据库或其他形式的持久化存储中。
事务是故障恢复和并发控制的基本单位,事务的几个特性可能遭到破坏的因素有:
a. 多个事务并行运行,不同事务的操作交叉执行;
b. 事务在运行过程中被强制停止。
二、 多个事务并发运行可能会导致的问题
1) 读脏(Dirty Reads)
读脏发生在一个事务读取了另一个事务改写但尚未提交的数据时。如果改写的数据稍后被回滚了,那么第一个事务获取的数据就是无效的。比如:事务A修改了数据库中的数据D的值为1000(假设原来为800),这时候事务B读取了D的值为1000,但是后来事务A回滚了修改操作,那么D的值变为800了,那么事务B读取的数据是与数据库中的不一致,是无效数据。
2) 不可重复读(Nonrepeatabe read)
不可重复读发生在一个事务执行相同的查询两次或两次以上,但是每次都得到不同的数据时。通常是因为另一个并发事务在两次查询期间更新了数据。
3) 幻读(Phantom read)
幻读与不可重复读类似。它发生在一个事务A读取了几行数据,接着另一个并发事务B插入了一些数据时。在随后的查询中,第一个事务A就会发现多了一些原本不存在的记录。
4) 丢失修改(Lost Update)
两个事务T1和T2读取同意数据并修改,T2提交结果破坏了T1提交的结果,导致T1的修改丢失。比如事务T1和T2读取机票余额为16张,T1事务售卖一张后修改为余票为15,T2事务售卖机票之后同样修改为15张。
三、事务隔离级别
隔离级别定义了一个事务可能受其他并发事务影响的程度。在理想的情况下,事务之间是完全隔离的,从而可以防止多个事务并发带来的读脏、不可重复读、幻读等问题。但是完全的隔离会导致性能问题,因为通常会涉及锁定数据库中的记录。这样的锁定会阻碍并发性,要求事务互相等待以完成各自的工作。
考虑到完全的隔离会导致性能问题,而且并不是所有的应用程序都需要完全的隔离,所以有时应用程序需要在事务隔离上有一定的灵活性,就会有不同的隔离级别。
1) java中隔离级别有如下几种,在java的Connection中可以设置 setTransactionIsolation(int leave) 方法设置该连接的事务隔离级别:
1、READ_COMMITTED 表示只读别的事务提交了的数据。这样可以防止脏数据的发生,但解决不了不可重复读和幻读
2、RRPEATABLE_READ 表示不可发生脏读和不可重复读, 幻读还是可能发生。
3 、SERIALIZABLE 表示所有的情况都不允许发生
但是 其中等级设置的越高,效率也就越低了, 一般设置为READ_COMMITTED
2)spring的事务隔离级别
1、ISOLATION_DEFAULT 使用后端数据库默认的隔离级别
2、 ISOLATION_READ_UNCOMMITTED 允许读取尚未提交的数据变更,可能会导致读脏、幻读或不可重复读
3、ISOLATION_READ_UNCOMMITTED 允许读取并发事务已经提交的数据,可以阻止读脏,但是幻读或不可重复读仍可能发生
4、 ISOLATION_REPEATABLE_READ 对同一字段的多次读取结果一致的,除非数据是被本事务自己所修改。可以阻止读脏和不可重复读,但仍可能发生幻读
5、 ISOLATION_SERIALIZABLE 完全服从ACID的隔离级别,确保阻止读脏、不可重复读及幻读。这是最慢的事务隔离级别,因为是通过完全锁定事务相关的数据库表来实现的。
四、 封锁
封锁是实现并发控制的一个非常重要的技术。所谓封锁就是事务T在对某个数据对象;例如表、记录等操作之前,先向系统发出请求,对其加锁。加锁后事务T就对该数据对象有了一定的控制,在事务T释放它的锁之前,其他的事务不能更新此数据对象。
确切的控制由封锁的类型决定。基本的封锁类型由两种:排它锁(Exclusive Locks,简称X锁)和共享锁(Share Locks,简称S锁)
排他锁又称为写锁。若事务T对数据对象A加上X锁,则只允许T读取和修改A,其他的任何事务不能对A加任何类型的锁,直到T释放A上的锁。这就保证了其他事务在T释放A上的锁之前不能在读取和修改A。
共享锁又称读锁。若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能对其加S锁,而不能加X锁,直到T释放A上的S锁。这就保证了其他事务可以读A,但在T释放A上的锁之前不能对A做任何修改。
关于事务的基本知识就说到这儿了,关于事务的配置和使用将在以后的文章中写道。
标签:
原文地址:http://blog.csdn.net/jcncsdn/article/details/51326372