数据库事务是使用Oracle经常会遇到的一个问题,实际的开发工作中对于数据库事务的应用是比较多的,那么对事务的熟悉也经常会成为面试的一个考点之一。可以测试一下开发人员的基本功以及数据库的掌握深度。下面我们要说一下Oracle相关的事务了。
1.事务概要
事务是不可分割的一系列数据库操作,这些操作要么整体成功,要么整体失败。 事务维护数据完成性,保证数据库在一个一致性状态。
事务可以看成是一个独立的逻辑单元,由一系列整体成功或失败的SQL语句组成。
2.Oracle事务
事务的四个基本特性ACID,原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
- 原子性:整个操作必须被完成或者终止,不能部分完成。
- 一致性:事务把资源从一个一致性状态带到另一个一致性状态。
- 隔离性:事务在提交前,一个事务相对与另一个事务是不可见的。
- 持久性:提交后的事务改变是永久的,就算系统重启或者失败都是可以恢复的。
2.1 事务隔离级别
SQL标准定义了四个隔离级别,分别是未提交读(Read Uncommitted)、提交读(Read Committed)、可重复读(Repeatable Read)、串行(Serializable)。以上4个隔离级别对应的并发性能逐次变差。
事务并发访问书库库是存在幻读,不可重复读,脏读等问题
- 幻读:例如事务T1读取数据的数量或者排序结果,返回结果集。此时事务T2插入一条新纪录并Commit,此时事务1再次查询的时候其结果集可以看到事务T2插入的记录。即两次读取的数据集数量不同。
- 不可重复读:事务T1读取一行记录,紧接着事务T2修改了刚刚的记录并提交,T1再次查询发现与刚才插入的数据不同。即两次读取的同一行数据不同。
- 脏读:事务T1更新了一条记录,暂时未提交,T2读取了跟新后的数据,然后T1回滚了刚才的操作,此时T2读取的数据是无效的,即脏数据。即读取了无效的数据。
隔离级别对应可能产生的问题
隔离层 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
Read Uncommitted | 是 | 是 | 是 |
Read Committed | 否 | 是 | 是 |
Repeatable Read | 否 | 否 | 是 |
Serializable | 否 | 否 | 否 |
Oracle数据库支持的隔离级别如下提交读(Read Committed)、串行(Serializable)、只读(Read Only),其并发性逐次降低。
默认情况下,Oracle中的事务在其他用户提交工作之后马上会允许读取,即Read Committed。所以默认情况下可能会发生不可重复读或幻读,而且不可能发生脏读。
2.2 开始和结束事务
Oracle数据库中,事务时从会话的第一个DML操作开始,直到遇到commit或者rollback结束。这是一个事务,之后再开启一个DML操作,则会开始一个新的事务,
3. Oracle分布式事务
在分布式数据库环境下,我们的事务对象横跨多个数据库对象。为了保证ACID的事务基本特性,从而有了分布式事务的概念。
我们这里说的是Oracle的分布式事务。如果是通过其他中间件来实现分布式事务,这里先不讨论。
Oracle分布式事务中有几个概念。
- Local Coordinator 分布式事务中,必须参考其他节点上的数据才能完成自己的操作的站点。
- Global Coordinator 分布式事务的发起者,负责协调这个分布式事务。
- Commit Point Site 在分布式事务中,首先执行COMMIT或rollback的站点。
Oracle分布式事务一般分3个提交过程。
- 准备阶段
- 本地数据库向其他数据库发出COMMIT通知
- 比较所有数据库的SCN号,以最高的SCN号作为全局SCN号
- 所有数据库在线写日志
- 对分布事务修改的表加分布锁,防止被读写
- 各个数据库向本地数据库发出已经准备好的通知
- 提交阶段
- 本地数据库通知commit point site首先提交。commit point site提交后,释放其占有的资源,通知Global Coordinator完成提交
- 本地数据库Global Coordinator通知其他数据库提交
- 提交节点在日志中追加一条信息,表示事务已经提交,并通知Global Coordinator。此时所有数据库的数据保持了一致性。
- 注销阶段
- 本地和数据库通知commit point site所有数据库已经完成提交
- commit point site清楚分布事务的记录和状态信息,并通知Global Coordinator
- Global Coordinator清楚本地分布事务的记录和状态信息
此时分布式事务两阶段提交全部完成。
总结
事务在日常开发中使用非常多,自然都是我们的学习的重点。事务使用时也会有许多的坑,那么我们后面也会介绍一下事务使用过程中踩过的坑。尽情期待吧!