一个oracle事务的完整执行流程

本文详细介绍了Oracle服务器进程处理用户请求的步骤,包括SQL语句解析、数据块读入db buffer、日志记录、事务回滚段建立、数据修改和提交或回滚操作。在SQL解析阶段,服务器会分析语法、生成执行计划并缓存。在数据处理中,涉及读取、锁管理、redo log记录和回滚段的使用。提交或回滚时,Oracle确保数据的一致性和完整性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

服务进程如何处理用户进程的请求

服务器进程在完成用户进程的请求过程中,主要完成如下7个任务:


0.sql语句的解析

1.数据块的读入db buffer

2.记日志

3.为事务建立回滚段

4.本事务修改数据块

5.放入dirty list

6.用户commit或rollback

0.sql语句的解析

 

 

 

 

下面要讲oracle服务器进程如可处理用户进程的请求,当一用户进程提交一个sql时:update temp set a=a*2;首先oracle服务器进程从用户进程把信息接收到后,在PGA中就要此进程分配所需内存,存储相关的信息,如在会话内存存储相关的登录信息等;服务器进程把这个sql语句的字符转化为ASCII等效数字码,接着这个ASCII码被传递给一个HASH函数,并返回一个hash值,然后服务器进程将到shared pool中的library cache中去查找是否存在相同的hash值,如果存在,服务器进程将使用这条语句已高速缓存在SHARED POOLlibrary cache中的已分析过的版本来执行,如果不存在,服务器进程将在CGA中,配合UGA内容对sql,进行语法分析,首先检查语法的正确性,接着对语句中涉及的表,索引,视图等对象进行解析,并对照数据字典检查这些对象的名称以及相关结构,并根据ORACLE选用的优化模式以及数据字典中是否存在相应对象的统计数据和是否使用了存储大纲来生成一个执行计划或从存储大纲中选用一个执行计划,然后再用数据字典核对此用户对相应对象的执行权限,最后生成一个编译代码ORACLE将这条sql语句的本身实际文本、HASH值、编译代码、与此语名相关联的任何统计数据和该语句的执行计划缓存在SHARED POOLlibrary cache中。服务器进程通过SHARED POOL 锁存器(shared pool latch)来申请可以向哪些共享PL/SQL区中缓存这此内容,也就是说被SHARED POOL锁存器锁定的PL/SQL区中的块不可被覆盖,因为这些块可能被其它进程所使用。在SQL分析阶段将用到LIBRARY CACHE,从数据字典中核对表、视图等结构的时候,需要将数据字典从磁盘读入LIBRARY CACHE,因此,在读入之前也要使用LIBRARY CACHE锁存器(library cache pinlibrary cache lock)来申请用于缓存数据字典。

 

到现在为止,这个sql语句已经被编译成可执行的代码了,但还不知道要操作哪些数据,所以服务器进程还要为这个sql准备预处理数据。

 

 

 

 

1.数据块的读入db buffer

 

 

 

Oracle处理数据,都需要把数据读取到内存中(即db buffer中),首先服务器进程要判断所需数据是否在db buffer存在,如果存在且可用,则直接获取该数据,同时根据LRU算法增加其访问计数;如果buffer不存在所需数据,则要从数据文件上读取。首先服务器进程将在表头部请求TM锁(保证此事务执行过程其他用户不能修改表的结构),如果成功加TM锁,再请求一些行级锁(TX锁),如果TMTX锁都成功加锁,那么才开始从数据文件读数据,在读数据之前,要先为读取的文件准备好buffer空间。服务器进程需要扫面LRU list寻找free db buffer

<think>我们被要求解释Oracle触发器的执行流程和工作原理。根据提供的引用,特别是引用[2]和引用[3],我们可以总结如下: Oracle触发器是存储在数据库中的一种特殊对象,它在特定事件发生时自动执行(即“触发”)。这些事件通常是对表的DML操作(INSERT、UPDATE、DELETE)或DDL操作,甚至数据库系统事件(如启动或关闭)。 ### 触发器的执行流程 1. **事件发生**:当对数据库表执行DML操作(INSERT、UPDATE、DELETE)时,或者发生特定的系统事件(如数据库启动或关闭)时,会触发相应的触发器。 2. **触发器类型决定执行时机**: - **BEFORE触发器**:在触发事件(如INSERT、UPDATE、DELETE)执行之前运行。 - **AFTER触发器**:在触发事件执行之后运行。 - **INSTEAD OF触发器**:主要用于视图,代替直接对视图的操作,转而执行触发器定义的操作。 3. **行级与语句级**: - **行级触发器(FOR EACH ROW)**:对受DML操作影响的每一行都会触发一次。在行级触发器中,可以使用`:new`和`:old`伪记录来访问该行在操作之前和之后的值。 - **语句级触发器**:无论DML操作影响多少行,整个DML语句只触发一次。语句级触发器不能使用`:new`和`:old`伪记录。 4. **条件检查**:如果触发器带有`WHEN`条件,则在触发时会检查该条件。只有当条件为真时,才会执行触发器的主体部分;否则,跳过执行。 5. **执行触发器主体**:当满足条件时,执行触发器主体中定义的PL/SQL代码块或存储过程调用。 6. **事务处理**:触发器中的操作是作为触发事件所在事务的一部分。如果触发器执行失败,则整个事务会回滚,导致触发事件(即DML语句)也被回滚。 ### 工作原理 触发器的工作原理可以概括为以下步骤: 1. **事件检测**:数据库监控到有定义的事件发生(例如,在某个表上执行了INSERT语句)。 2. **触发器选择**:根据事件类型(INSERT、UPDATE、DELETE)和时机(BEFORE或AFTER),数据库选择符合条件的触发器。 3. **条件评估**:如果触发器定义了`WHEN`条件,则评估该条件。如果条件不满足,则跳过该触发器的执行。 4. **执行触发器**: - 对于行级触发器,数据库会为受影响的每一行执行一次触发器代码。在行级触发器中,可以通过`:new`和`:old`来引用当前行的新旧值。 - 对于语句级触发器,整个语句只执行一次触发器代码。 5. **原子性**:触发器的执行是原子性的,即触发器中的操作和触发事件(DML语句)是一个事务。如果触发器中的操作失败(例如抛出异常),则整个事务会回滚,包括触发事件所做的更改。 6. **多个触发器的执行顺序**:如果同一个事件有多个触发器,则它们的执行顺序可以通过`FOLLOWS`和`PRECEDES`子句(Oracle 11g及以后)来指定,否则执行顺序是不确定的(但通常按创时间顺序)。 ### 示例 假设有一个表`employees`,其上定义了一个BEFORE INSERT行级触发器: ```sql CREATE OR REPLACE TRIGGER before_emp_insert BEFORE INSERT ON employees FOR EACH ROW WHEN (NEW.salary < 0) BEGIN :NEW.salary := 0; -- 如果插入的工资为负数,则自动改为0 END; ``` 当执行一条INSERT语句向`employees`插入一行数据时,如果该行的salary值为负数,触发器会在插入操作发生之前将该值改为0。 ### 总结 Oracle触发器提供了一种在数据库层面自动执行业务规则和复杂约束的机制。它们由事件驱动,根据定义的时机(BEFORE/AFTER)和粒度(行级/语句级)执行,并且可以设置条件。触发器的主体通常是一个PL/SQL块,可以包含复杂的逻辑。需要注意的是,过度使用触发器可能导致性能问题,因为它们会在每次事件发生时执行,可能增加事务的开销。 [^1]: Oracle触发器概述 [^2]: Oracle触发器详解 [^3]: oracle触发器语句 §§相关问题§§ 1. Oracle触发器中BEFORE和AFTER触发器的使用场景有什么区别? 2. 在行级触发器中,如何访问修改前后的数据? 3. 如何控制同一个表上多个触发器的执行顺序? 4. 触发器执行过程中如果发生异常,会怎样影响事务?</think>### Oracle触发器执行流程及工作原理 #### 1. **触发器的基本概念** Oracle触发器是一种特殊的存储程序,由特定数据库事件(如INSERT、UPDATE、DELETE)自动触发执行,无需显式调用[^2]。其核心特点是: - **事件驱动**:由DML操作或系统事件(如数据库启动)激活。 - **隐式执行**:满足触发条件时自动运行,无法接收参数。 - **作用范围**:可定义在表或视图上,用于实现复杂业务规则约束或审计功能[^2]。 #### 2. **执行流程(分步解析)** ##### **步骤1:事件检测** 当用户执行DML操作(如`INSERT INTO employees(...)`)时,数据库检测是否存在关联触发器。 ##### **步骤2:时机判定** 根据触发器定义的时机选择执行阶段: - **BEFORE触发器**:在DML操作**前**执行(如数据校验)[^3]。 ```sql CREATE TRIGGER validate_salary BEFORE INSERT ON employees -- 插入前触发 FOR EACH ROW BEGIN IF :NEW.salary < 0 THEN RAISE_APPLICATION_ERROR(-20001, '薪资不能为负数'); END IF; END; ``` - **AFTER触发器**:在DML操作**后**执行(如审计日志记录)[^3]。 ##### **步骤3:行级/语句级处理** - **行级触发器(`FOR EACH ROW`)**: 影响N行数据则触发N次,可通过`:NEW`和`:OLD`伪记录访问数据变化: ```sql CREATE TRIGGER log_salary_change AFTER UPDATE ON employees FOR EACH ROW -- 每修改一行触发一次 BEGIN INSERT INTO audit_log VALUES(:OLD.salary, :NEW.salary, SYSDATE); END; ``` - `:OLD`:操作前的数据(DELETE/UPDATE时有效) - `:NEW`:操作后的数据(INSERT/UPDATE时有效) - **语句级触发器**: 无论影响多少行,整个DML语句**仅触发一次**(无`:NEW/:OLD`访问权限)[^3]。 ##### **步骤4:条件过滤(`WHEN`子句)** 若触发器包含`WHEN`条件,仅当条件满足时执行主体代码: ```sql CREATE TRIGGER high_salary_alert AFTER INSERT ON employees FOR EACH ROW WHEN (NEW.salary > 100000) -- 仅当薪资>10万时触发 BEGIN send_alert('高薪员工新增: ' || :NEW.name); END; ``` ##### **步骤5:事务绑定** 触发器执行与触发它的DML操作属于**同一事务**: - 成功:事务提交后所有修改生效。 - 失败:触发器抛出异常时,整个事务回滚(包括原始DML操作)[^2]。 #### 3. **关键机制详解** 1. **临时表机制** `:NEW`和`:OLD`是内存中的伪记录,提供行级数据变更的快照。例如: - UPDATE操作中,`:OLD.salary`代表旧值,`:NEW.salary`代表新值。 - 在BEFORE触发器中修改`:NEW`值可覆盖实际写入数据[^3]。 2. **执行顺序控制** 同一事件(如INSERT)的多个触发器,默认按创顺序执行Oracle 11g+可通过`FOLLOWS`指定顺序: ```sql CREATE TRIGGER trig2 AFTER INSERT ON emp FOLLOWS trig1 -- 明确在trig1之后执行 ... ``` 3. **递归与级联** 触发器内部执行DML可能触发其他触发器(递归)。需避免无限循环,可通过`ALTER TRIGGER trigger_name DISABLE`临时禁用[^3]。 #### 4. **典型应用场景** - **数据完整性**:实现跨表约束(如部门预算校验)。 - **审计跟踪**:自动记录关键表的数据变更历史。 - **派生数据**:实时更新汇总表(如订单总额计算)。 - **安全控制**:禁止非工作时间修改数据。 > ⚠️ **注意事项**: > 过度使用触发器可能导致性能下降(尤其是行级触发器),议将复杂逻辑移至存储过程,仅用触发器处理必要事件[^2]。 [^1]: Oracle触发器概述 [^2]: Oracle触发器详解 [^3]: oracle触发器语句
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值