<meta charset="utf-8">
Jim Gray在1981年提出《The Transaction of Concept》由此正式拉开数据库支持事务的机制,MyISAM不支持事务,而更早的ISAM(Indexed Sequential Access Method)更不支持。
事务特性(ACID)
- 原子性
- 一致性
- 隔离性
- 持久性
隔离级别
读未提交——发生脏读:脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是脏数据,依据脏数据所做的操作可能是不正确的。
读已提交——发生不可重复读(虚读、原始读取不可重复、原始读取不可重现):在一个事务内,多次读同一个数据。在这个事务还没有结束时,另一个事务也访问该同一数据。那么,在第一个事务的两次读数据之间。由于第二个事务的修改,那么第一个事务读到的数据可能不一样,这样就发生了在一个事务内两次读到的数据是不一样的,因此称为不可重复读,即原始读取不可重复。
可重复读——发生幻读:Transaction1读取满足某种搜索条件的一些行,然后Transaction2插入了符合Transaction1的搜索条件的一个新行。如果Transaction1重新执行产生原来那些行的查询,就会得到不同的行。
串行化——排除所有:在这个事务没有被提交之前 其他的线程,只能等到当前操作完成之后,才能进行操作。
原始读取不可重复的重点在于update和delete,而不可重复读(幻读)的重点在于insert。
如果使用锁机制来实现这两种隔离级别,在可重复读中,该sql第一次读取到数据后,就将这些数 据加锁,其它事务无法修改这些数据,就可以实现可重复读了。但这种方法却无法锁住insert的数据,所以当事务A先前读取了数据,或者修改了全部数据,事务B还是可以insert数据提交,这时事务A就会 发现莫名其妙多了一条之前没有的数据,这就是幻读,不能通过行锁来避免。需要Serializable隔离级别 ,读用读锁,写用写锁,读锁和写锁互斥,这么做可以有效的避免幻读、不可重复读、脏读等问题,但会极大的降低数据库的并发能力。
事务的分类
1.扁平事务(falt transaction):原子性的基本模块功能支持,由BEGIN WORK开始,由COMMIT WORK或ROLLBACK WORK结束,其间的操作都是原子的。要么执行,要么回滚。
2.带有保存点的扁平事务(flat transaction with savepoint):在基于扁平事务的基础上,允许在事务执行过程中回滚到事务中较早的一个状态。
begin work(隐含save work 1) action1 action2 save work 2 action3 save work3 action4 roolback work:2
3.链事务(chained transaction)
可视为保存点模式的一种变种。带有保存点的扁平事务,当发生系统崩溃时,所有的保存点都将消失,因为保存点是易失的,而非持久的。
链事务的思想:在提交一个事务时,释放不需要的数据对象,将必要的处理上下文隐式地传给下一个要开始的事务。注意,提交事务操作和开始下一个事务操作合并为一个原子操作。这意味着下一个事务将看到上一个事务的结果,就好像在事务中进行一样。
第一个事务的提交触发第二个事务的开始。
只能恢复最近一个的保存点。
4.嵌套事务(nested transaction)
嵌套事务是一个层次结构框架。由一个层次事务控制着各个层次的事务。层次事务之下嵌套的事务被称为子事务,其控制每一个局部的变换。
相当于是一颗树。子树可以是嵌套也可以是扁平事务。
叶子节点的事务是扁平事务。
实际的工作交给叶子节点完成,即只有叶子节点的事务才能访问数据库、发送消息、获取其他类型的资源。高层事务仅负责逻辑控制,决定何时调用相关的子事务。
嵌套查询中,事务p1持有x,y的锁,开始调用子事务p11,那么父事务p1可以传递或不传递锁,如果p11中还持有y锁,那么p1会持有x,y,z锁。
5.分布式事务(distributed transaction)
通常是在一个分布式环境下运行的扁平事务,因此需要根据数据所在位置访问网络中的不同节点。