事务的四个属性:原子性(atomicity)、一致性(consistency)、隔离性(isolation)和持久性(durability)
PROPAGATION_REQUIRED -- 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS -- 支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY -- 支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW -- 新建事务,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NOT_SUPPORTED -- 以非事务方式执行,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER -- 以非事务方式执行,如果当前存在事务,就抛出异常。
PROPAGATION_NESTED -- 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与 PROPAGATION_REQUIRED 类似的操作。
前六个策略类似于 EJB CMT,第七个(PROPAGATION_NESTED)是 Spring 所提供的一个特殊变量。
它要求事务管理器或者使用 JDBC 3.0 Savepoint API 提供嵌套事务行为(如 Spring 的 DataSourceTransactionManager)
数据库并发操作存在的异常情况:
脏读(Dirty Reads): 一个事务开始读取了某行数据但是另外一个事务已经更新了此数据但没有能够及时提交。
不可重复读(Non-repeatable Reads): 一个事务对同一行数据重复读取两次但是却得到了不同结果。例如在两次读取中有另外一个事务对该行数据进行了修改并提交
幻读(Phantom Reads): 事务在操作过程中进行两次查询,第二次查询结果包含了第一次查询中未出现的数据, 这是因为在两次查询过程中有另外一个事务插入数据造成的
为避免上面出现几种情况在标准 SQL 规范中定义了 4 个事务隔离级别,不同隔离级别对事务处理不同:
隔离级别 脏读取 重复读取 幻读
未授权读取(Read Uncommitted) Y Y Y
授权读取(Read Committed) N Y Y
可重复读取(Repeatable Read) N N Y
串行(Serializable) N N N
在数据库中有两种基本的锁类型:
排它锁(eXclusive Locks,即 X 锁)
当数据对象被加上排它锁时,其他的事务不能对它读取和修改。
共享锁(Share Locks,即 S 锁)
当数据对象被加上共享锁时,可以被其他事务读取,但不能修改。数据库利用这两种基本的锁类型来对数据库的事务进行并发控制。
从程序的角度看, 锁分为以下两种类型:
乐观锁(Optimistic Lock)
乐观锁假定在处理数据时,不需要在应用程序的代码中做任何事情就可以直接在记录上加锁、即完全依靠数据库来管理锁的工作。一般情况下,当执行事务处理时数据库会自动对事务处理范围内更新到的表做锁定。
悲观锁(Pessimistic Lock)
悲观锁对数据库系统的自动管理不感冒,需要程序员直接管理数据或对象上的加锁处理,并负责获取、共享和放弃正在使用的数据上的任何锁。
* 事务是有代价的,不是所有系统都弄个事务。这是个仁者见仁智者见智的问题,比如 OSC 就没弄这玩意,上次聚会听红薯说的,我觉得很对。具体问题具体分析嘛。