Oracle commit之后做了什么
在 Oracle 数据库中,`COMMIT` 语句是事务管理中的核心命令,用于将当前事务中的所有修改操作永久保存到数据库中,并结束当前事务。以下是 `COMMIT` 语句的具体作用和工作原理的详细解析:
### 1. **数据持久化**
- **作用**:`COMMIT` 确保事务中的所有数据修改(如 `INSERT`、`UPDATE`、`DELETE` 等 DML 操作)被写入数据库的物理存储中,保证数据的持久性(Durability),即使系统发生故障,数据也不会丢失。
- **过程**:在执行 `COMMIT` 之前,DML 操作的修改仅存在于内存(SGA 的缓冲区)中,`COMMIT` 会触发将这些修改写入重做日志文件(redo log file)。随后,数据库后台进程(如 DBWR)会在适当的检查点(checkpoint)将数据写入数据文件(data file)。从用户角度看,`COMMIT` 完成后数据已被永久保存。[](https://geek-docs.com/oracle/oracle-questions/358_oracle_what_does_commit_do-2.html)[](https://cloud.tencent.cn/developer/article/1073252)
### 2. **生成 SCN(System Change Number)**
- **作用**:每次执行 `COMMIT`,Oracle 会为事务生成一个唯一的 SCN(系统变更号),用于标识事务的顺序,确保数据库的读一致性和故障恢复。
- **机制**:SCN 是一个递增的时序机制,类似于数据库的“时钟”,每次 `COMMIT` 会使 SCN 增加,用于跟踪事务的提交时间点和数据状态。[](https://blog.csdn.net/huangyanlong/article/details/27230733)
### 3. **释放锁**
- **作用**:`COMMIT` 会释放事务期间持有的所有锁(如表级锁或行级锁),允许其他会话访问和修改相关数据,从而减少并发冲突。
- **细节**:在事务执行期间,DML 操作(如 `INSERT`、`UPDATE`、`DELETE`)可能会对表或行加锁,阻止其他事务操作相同的数据。`COMMIT` 完成后,这些锁被释放,等待这些锁的其他会话可以继续工作。[](https://geek-docs.com/oracle/oracle-questions/358_oracle_what_does_commit_do-2.html)[](https://www.cnblogs.com/rsyslog/p/13950746.html)
### 4. **块清理(Block Cleanout)**
- **作用**:`COMMIT` 会清理数据库块头部中与事务相关的锁信息(block cleanout),以便后续访问这些块的会话无需再次处理事务信息。
- **优化**:块清理以快速模式执行,且不生成额外的重做日志(redo log),从而减少后续操作的开销。[](https://blog.csdn.net/huangyanlong/article/details/27230733)
### 5. **事务结束**
- **作用**:`COMMIT` 标记事务的结束,从 `V$TRANSACTION` 视图中移除事务条目,表示事务已完成。
- **影响**:事务提交后,其他会话可以查询到修改后的数据,而在提交前,只有当前会话能看到这些修改(事务隔离性)。[](https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/COMMIT.html)
### 6. **日志文件同步(Log File Sync)**
- **作用**:`COMMIT` 会触发日志写入进程(LGWR)将剩余的缓存重做日志(redo log buffer)写入磁盘上的重做日志文件,确保事务的修改记录被持久化。
- **性能特点**:`COMMIT` 的响应时间通常是“平坦的”(flat),即无论事务大小如何,提交时间几乎恒定。这是因为大部分数据修改工作(如生成 redo、undo 等)在 `COMMIT` 之前已经完成,`COMMIT` 仅需完成少量收尾工作。[](https://blog.csdn.net/hzhsan/article/details/9719307)[](https://www.cnblogs.com/rsyslog/p/13950746.html)
### 示例
以下是一个简单的 `COMMIT` 使用示例:
```sql
BEGIN
INSERT INTO employees (id, name) VALUES (1, 'John');
INSERT INTO employees (id, name) VALUES (2, 'Jane');
COMMIT; -- 提交事务,数据永久保存
END;
```
在这个例子中,`COMMIT` 确保两条 `INSERT` 操作的修改被持久化到数据库,并释放相关锁。
### 与 ROLLBACK 的区别
- **COMMIT**:将修改永久保存到数据库,释放锁,其他会话可见修改。
- **ROLLBACK**:撤销事务中的所有修改,恢复到事务开始前的状态,保持锁直至事务结束。[](https://geek-docs.com/oracle/oracle-questions/358_oracle_what_does_commit_do-2.html)
### 注意事项
1. **隐式提交**:某些 DDL 操作(如 `CREATE`、`ALTER`、`DROP`)会自动触发 `COMMIT`,无需显式执行。[](https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/COMMIT.html)
2. **性能优化**:避免频繁提交(如逐行提交),因为每次 `COMMIT` 都会触发日志同步,增加与数据库的通信开销。建议在逻辑工作单元完成后提交,以减少资源竞争。[](https://blog.csdn.net/hzhsan/article/details/9719307)
3. **PL/SQL 优化**:在 PL/SQL 中,`COMMIT` 是异步的,提交操作会在 PL/SQL 程序返回客户端时统一等待 LGWR 完成,从而减少多次提交的等待时间。但频繁提交仍不推荐。[](https://www.cnblogs.com/rsyslog/p/13950746.html)
### 总结
Oracle 的 `COMMIT` 语句通过持久化数据、生成 SCN、释放锁、清理块和结束事务,确保事务的原子性、一致性、隔离性和持久性(ACID)。它是一个快速且高效的操作,对数据库性能和数据完整性至关重要。合理使用 `COMMIT`,并在逻辑工作单元完成后提交,可以优化数据库性能并保证数据可靠性。[](https://geek-docs.com/oracle/oracle-questions/358_oracle_what_does_commit_do-2.html)[](https://blog.csdn.net/hzhsan/article/details/9719307)[](https://geek-docs.com/oracle/oracle-questions/358_oracle_what_does_commit_do.html)