事务是一组不可分割的数据库操作,这些操作要么全部成功(提交),要么全部失败(回滚)。事务管理是数据库管理系统(DBMS)中的一个关键特性,它确保了数据库在并发操作下的稳定性和一致性。
1. 事务的基本属性 (ACID)
事务具有四个基本属性,统称为 ACID 属性:
-
Atomicity(原子性):事务中的所有操作要么全部执行成功,要么全部不执行。即便事务中的某个操作失败,整个事务也会回滚到事务开始前的状态。
-
Consistency(一致性):事务在开始和结束时,数据库的状态必须是一致的。即,事务的执行不能破坏数据库的约束和规则。
-
Isolation(隔离性):多个事务并发执行时,一个事务的执行结果不应影响其他事务的执行。Oracle 通过不同的隔离级别来控制并发事务之间的相互影响。
-
Durability(持久性):一旦事务提交(COMMIT),其结果就会永久保存到数据库中,哪怕系统崩溃也不会丢失。
2. 事务的基本操作
Oracle 中事务的基本操作包括:
-
BEGIN TRANSACTION(隐式启动事务):在 Oracle 中,事务通常隐式地启动。每当你执行一条
INSERT
、UPDATE
、DELETE
或SELECT FOR UPDATE
语句时,事务就自动开始了。 -
COMMIT(提交):提交事务,将事务中的所有更改永久保存到数据库中。
COMMIT;
-
ROLLBACK(回滚):回滚事务,撤销事务中的所有未提交的更改,使数据库恢复到事务开始前的状态。
ROLLBACK;
-
SAVEPOINT(保存点):在事务中创建一个保存点,允许你回滚到事务中的某个特定点,而不是回滚整个事务。
SAVEPOINT savepoint_name;
-
ROLLBACK TO SAVEPOINT(回滚到保存点):将事务回滚到之前定义的保存点。
ROLLBACK TO savepoint_name;
3. 事务控制示例
假设你有一个名为 employees
的表,现在你要更新员工的薪水,并根据不同情况决定是否提交或回滚事务:
-- 开始事务(隐式) UPDATE employees SET salary = salary * 1.1 WHERE department_id = 10; SAVEPOINT before_bonus; -- 给销售部门的员工增加奖金 UPDATE employees SET salary = salary + 1000 WHERE department_id = 20; -- 检查某些条件,如果不满足,回滚奖金更新 ROLLBACK TO before_bonus; -- 最后提交所有更改 COMMIT;
在这个例子中:
- 更新了部门ID为10的员工的薪水,隐式启动了一个事务。
- 创建了一个保存点
before_bonus
。 - 更新了部门ID为20的员工的薪水,增加了奖金。
- 如果某些条件不满足,可以回滚到保存点
before_bonus
,撤销奖金更新,但保留之前的薪水更新。 - 最终,提交整个事务,将更改永久保存。
4. 事务隔离级别
Oracle 支持四种事务隔离级别,用于控制事务之间的相互影响:
-
READ UNCOMMITTED:允许一个事务读取其他事务尚未提交的更改。可能导致脏读(Dirty Read)问题。Oracle 默认不支持这个隔离级别。
-
READ COMMITTED(默认隔离级别):只允许事务读取其他已提交的更改。可以防止脏读,但可能会出现不可重复读(Non-repeatable Read)问题。
-
REPEATABLE READ:保证在事务内多次读取相同数据时,数据是一致的(即其他事务不能修改或删除该数据)。可以防止脏读和不可重复读,但不能防止幻读(Phantom Read)。Oracle 使用快照隔离来提供类似的效果。
-
SERIALIZABLE:提供最高的隔离级别,强制事务串行执行,防止脏读、不可重复读和幻读,但代价是降低了并发性。
5. 自动提交与显式事务控制
在一些情况下(如使用 SQL*Plus 或其他工具),SQL 语句可能会自动提交。要完全控制事务,建议显式使用 COMMIT
和 ROLLBACK
。
6. 事务的并发控制
Oracle 使用多版本并发控制(MVCC,Multi-Version Concurrency Control)来管理事务并发性。每个事务会看到一个一致性的快照,这意味着事务在执行期间,看到的数据与其他事务不会相互影响。这种机制可以有效地减少锁争用并提高并发性能。