深入Spring事务之一:数据库事务基础知识

 

基础


谈Spring的事务之前,我们有必要对数据库事务的知识有个全面了解。
一荣俱荣,一损俱损很能体现事务的思想。
数据库事务有严格的定义,必须满足四个特性:

  1. 原子性(Atomic) :表示组成一个事务的多个数据库操作是一个不可分割的原子单元,只有所有操作执行成功,整个事务才提交。
  2. 一致性(Consistency): 事务操作成功后,数据库所处的状态和它的业务规则是一直的,即数据不会被破坏。
  3. 隔离性(Isolation): 在并发数据操作时,不同的事务拥有各自的数据空间,他们的操作不会对对方产生干扰。
  4. 持久性(Durability): 一旦事务提交成功后,事务中所有的数据操作都必须被持久化到数据库中。

在这些特性中,数据“一致性”是最终目标,其他特性都是未达到这个目标的措施、要求和手段。

 

数据并发


数据并发的问题,数据库中的相同数据可能被多个事务访问,就会导致各种并发问题。下面来看一下数据并发引发的问题。
脏读(dirty read):A事务读取B事务尚未提交的更改数据,并在这个数据的基础上操作。

时间转账事务A转账事务B
T1   开始事务
T2 开始事务  
T3   查询余额为1000元
T4   取出500,余额为500
T5 查询500元(脏读)  
T6   撤销事务,余额恢复1000元
T7 汇入100,余额为600元  
T8 提交事务  

不可重复读(unrepeatable read):A事务读取了B事务已经提交的更改数据。

时间转账事务A转账事务B
T1   开始事务
T2 开始事务  
T3   查询余额为1000元
T4 查询余额为1000元  
T5   取出100,余额为900
T6   撤销事务,余额恢复1000元
T7   提交事务
T8 查询余额为900元(与T4不一样)  

幻象读(phantom read):A事务读取B事务提交的新增数据,这时A事务将出现幻象读问题。

时间转账事务A转账事务B
T1   开始事务
T2 开始事务  
T3 总款项为10000元  
T4   新增一存款客户,存入10000元
T5   提交事务
T6 再次计算为10100元  
幻象读和不可重复读容易混淆,前者是指读到了其他已经提交事务的新增数据,而后者是指读到了已经提交事务的更改数据。为了避免这两种情况,采取的对策是不同的:防止读取到更改数据,只需要对操作的数据添加行级锁,阻止操作中的数据发生变化;而防止读取到新增数据,往往需要添加表级锁—将整个表锁住,防止新增数据(Oracle使用多版本数据的方式实现)。

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

时间转账事务A转账事务B
T1 开始事务  
T2   开始事务
T3 查询余额为1000元  
T4   查询余额为1000元
T5   汇入100,余额为1100
T6   提交事务
T7 取出100,改为900  
T8 撤销事务  
T9 余额恢复为1000(丢失更新)  

第二类丢失更新:A事务覆盖B事务中已经提交的数据,造成B事务所做操作丢失。

时间转账事务A转账事务B
T1   开始事务
T2 开始事务  
T3   查询余额为1000元
T4 查询余额为1000元  
T5   取出100,余额为900
T6   提交事务
T7 汇入100  
T8 提交事务  
T9 余额该为1100(丢失更新)  

 

锁机制:


数据库通过锁机制解决并发问题。按照锁定对象的不同,一般可以分为行锁定和表锁定。 不同数据库在实现锁机制的时候细节不同,但是基本原理都是一样的。下面看Oracle数据库常用的五种锁定:

1.行共享锁定:一般通过select for update语句隐式获得行共享锁定。行共享锁定并不放置对数据进行更改的操作,但是可以放置其他会话获取独占性数据表锁定
2.行独占锁定:通过一条insert、update或delete语句隐式获取。这个锁定可以放置其他会话获取一个共享锁定、共享行独占锁定或独占锁定。
3.表共享锁定:可以防止其他会话获取行独占锁定,或者防止其他表共享行独占锁定或表独占锁定 4.表独占锁定:可以防止其他会话获取一个表共享、行独占或者表独占锁定,它允许其他行共享锁定
5.表独占:这个锁定防止其他会话对该表的任何其他锁定

 

事务隔离级别


数据库中,直接使用锁管理是非常麻烦的,因此数据库提供了自动锁机制,只要用户指定会话的事务隔离级别,数据库就会分析事务中的SQL语句,然后自动为事务操作的数据库添加上适合的锁。此外数据库还会维护这些锁。
ANSI/ISO SQL 92标准定义了4个等级的事务隔离级别,在相同环境下,使用不同隔离级别,可以导致不同的结果。

隔离级别脏读不可重复读幻象读第一类丢失更新第二类丢失更新
READ UNCOMMITED 允许 允许 允许 不允许 允许
READ COMMITTED 不允许 允许 允许 不允许 允许
REPEATABLE READ 不允许 不允许 允许 不允许 不允许
SERIALIZABLE 不允许 不允许 不允许 不允许 不允许

SQL 92推荐使用REPEATABLE READ以保证数据的读一致性,不过这是可以选择的.

   Mysql中,查看系统事务隔离级别:SELECT @@global.tx_isolation




posted @ 2023-08-04 15:42  轩辕李  阅读(39)  评论(0)    收藏  举报