1. 重做日志缓冲区(Redo Log Buffer)
1.1 概述
重做日志缓冲区是Oracle数据库中用于存储用户对数据库所作修改的临时区域。在用户执行数据操作语言(DML)或数据定义语言(DDL)命令时,如INSERT
、UPDATE
、DELETE
,或者CREATE
、DROP
、ALTER
等操作,数据库首先会将这些操作的重做日志记录到重做日志缓冲区中。随后,数据文件中的数据才会被实际修改。
1.2 工作机制
当用户对数据库进行修改时,数据库会将这些修改操作的重做日志信息暂时存储在重做日志缓冲区中,随后由后台进程LGWR
(Log Writer)在适当的时机将这些日志信息写入重做日志文件。这种方式可以保证在数据库系统出现故障时,能够通过重做日志文件中的信息对数据库进行恢复。
举例:
- 用户在数据库中执行了一条
UPDATE
语句来修改某个表中的数据。 - Oracle数据库会将这次
UPDATE
操作的相关信息(如修改前后的数据)写入到重做日志缓冲区中。 - 在适当的时间点,
LGWR
进程会将重做日志缓冲区中的信息写入到磁盘上的重做日志文件中,以确保数据的持久性。
1.3 参数配置
重做日志缓冲区的大小由初始化参数LOG_BUFFER
来指定。默认情况下,LGWR
进程在以下情况之一发生时,将重做日志缓冲区中的内容写入磁盘:
- 重做日志缓冲区已满;
- 用户提交事务(
COMMIT
); - 定期的时间间隔。
举例:
- 如果
LOG_BUFFER
设置为5MB,当用户进行大量数据修改时,缓冲区很快就会被填满,LGWR
进程将立即开始将缓冲区中的日志信息写入磁盘。 - 如果缓冲区较大,例如设置为50MB,那么
LGWR
进程可能不会那么频繁地写入磁盘,这样可以减少I/O操作,提高数据库的整体性能。
2. 共享池(Shared Pool)
2.1 概述
共享池是SGA(系统全局区)的一部分,用于存放最近执行的SQL语句、解析后的SQL计划、以及与SQL语句执行相关的各种信息。共享池由多种缓存组成,主要包括库高速缓存(Library Cache)、数据字典高速缓存(Data Dictionary Cache),这些缓存用于提高SQL语句的执行效率。
2.2 工作机制
共享池的核心功能是缓存SQL语句及其解析结果。当用户提交一个SQL查询时,数据库服务器会首先检查共享池中是否存在该SQL语句的解析结果。如果存在,数据库将直接使用缓存中的结果,省去了重新解析SQL语句的时间;如果不存在,则会重新解析该SQL语句并生成新的执行计划,并将其存入共享池中,以便下次复用。
举例:
- 用户A执行了
SELECT ename, sal FROM emp WHERE empno=7902
查询。 - Oracle数据库会将该SQL语句及其解析结果(执行计划)存入共享池中。
- 如果用户B随后执行相同的SQL查询,由于该查询已经存在于共享池中,Oracle将直接使用缓存的执行计划,这样可以显著减少查询时间。
2.3 参数配置
共享池的大小由初始化参数SHARED_POOL_SIZE
来指定,合理配置该参数可以避免共享池过小导致频繁的SQL重新解析,也可以防止共享池过大浪费内存资源。
举例:
- 如果
SHARED_POOL_SIZE
设置过小,比如10MB,当多个用户并发查询时,可能导致频繁的缓存替换,SQL语句需要反复解析,降低系统性能。 - 如果
SHARED_POOL_SIZE
设置为较大的值,如500MB,那么大多数SQL语句和解析结果可以长期保存在共享池中,从而减少解析次数,提高整体数据库性能。
详细举例:
1. 重做日志缓冲区(Redo Log Buffer)
例子1:批量数据更新
公司人力资源部门决定批量提高员工的工资,所有员工的工资增加10%。该操作涉及大量数据更新,具体操作如下:
UPDATE employees SET salary = salary * 1.1;
操作记录到重做日志缓冲区:
- Oracle首先将这次批量更新的每个
UPDATE
操作记录到重做日志缓冲区。此时,这些数据的实际变更尚未写入数据文件。 - 例如,员工
John Doe
的工资从5000
增加到5500
,这个变更首先记录在重做日志缓冲区中。
- Oracle首先将这次批量更新的每个
日志写入到重做日志文件:
- 随着更多的
UPDATE
操作填充重做日志缓冲区,当缓冲区达到一定的阈值时,LGWR
进程将缓冲区中的日志信息写入到磁盘上的重做日志文件中。 - 例如,当重做日志缓冲区已经记录了上百次的工资变更操作时,
LGWR
进程开始将这些日志写入到磁盘上的重做日志文件,以确保日志信息持久化。
- 随着更多的
数据提交:
- 最后,数据库用户提交事务(
COMMIT
),确保所有工资更新操作生效,此时所有变更数据被真正写入数据文件。
- 最后,数据库用户提交事务(
例子2:事务回滚
一个用户对数据库执行了多个INSERT
操作,但在执行完某个操作后发现操作有误,决定回滚整个事务。
INSERT INTO orders VALUES (1, 'A100', 200);
INSERT INTO orders VALUES (2, 'B200', 300);
-- 用户发现出错,决定回滚事务
ROLLBACK;
操作记录到重做日志缓冲区:
- 当用户执行
INSERT
操作时,每条INSERT
操作的相关数据都会被记录到重做日志缓冲区。此时,这些数据已经写入数据文件。
- 当用户执行
回滚操作:
- 当用户执行
ROLLBACK
操作时,数据库会读取重做日志缓冲区中的日志记录,找到相关的操作,并将对应的数据恢复到原始状态。这种情况下,重做日志缓冲区的记录确保了数据库能够回到回滚前的状态。
- 当用户执行
日志写入到重做日志文件:
- 在回滚操作后,Oracle仍会将重做日志缓冲区的内容写入到重做日志文件中,确保系统崩溃时仍可根据这些日志信息恢复回滚操作。
2. 共享池(Shared Pool)
2.1 共享池工作机制详细举例
例子1:SQL查询缓存
数据库中有一个名为customers
的表,记录了公司客户的详细信息。某个用户执行以下查询来获取客户信息:
SELECT name, email FROM customers WHERE city = 'New York';
SQL语句解析并存入共享池:
- 第一次执行该查询时,Oracle会解析SQL语句,生成执行计划,并将此解析结果存储在共享池中。
- 例如,Oracle可能生成的执行计划是:首先扫描
customers
表,然后通过索引查找city
列为New York
的记录,最后返回name
和email
列的数据。
复用解析结果:
- 之后,另一个用户执行相同的查询:
SELECT name, email FROM customers WHERE city = 'New York';
- Oracle会在共享池中查找该SQL语句及其解析结果,并直接使用之前缓存的执行计划,而无需重新解析,从而显著提高查询速度。
稍有不同的SQL语句:
- 如果第三个用户执行类似的查询,但指定不同的城市,如
Los Angeles
:
SELECT name, email FROM customers WHERE city = 'Los Angeles';
- 尽管这条语句和之前的查询结构非常相似,但由于
WHERE
子句中的条件不同,Oracle需要重新解析该SQL语句,并生成一个新的执行计划。这个新的执行计划也将存储在共享池中,以便将来复用。
- 如果第三个用户执行类似的查询,但指定不同的城市,如
例子2:存储过程的缓存
公司开发了一段存储过程,用于计算员工的年度奖金,代码如下:
CREATE OR REPLACE PROCEDURE calc_bonus IS
BEGIN
-- 计算逻辑
UPDATE employees SET bonus = salary * 0.1 WHERE department = 'Sales';
END;
存储过程存储到共享池:
- 当这个存储过程首次被调用时,Oracle会将其编译后的PL/SQL代码存入共享池的库高速缓存中。这样,下一次调用这个存储过程时,Oracle可以直接从共享池中获取,而无需重新编译。
复用编译结果:
- 当HR部门在年底调用
calc_bonus
存储过程来计算销售部员工的奖金时,Oracle会快速从共享池中获取之前存储的编译结果并执行该过程,大大提升了系统性能。
- 当HR部门在年底调用
更新存储过程:
- 如果管理员对
calc_bonus
存储过程进行了修改,Oracle会自动将旧版本从共享池中清除,并在下次调用时重新编译并存储新版本的编译结果。
- 如果管理员对
非常感谢您读到这里!如果您觉得这篇文章对您有帮助,可以关注一下博主。关注后,您将第一时间获得最新的AI、云计算、运维(Linux、数据库,容器等)技术,以及更多实用的技能干货。
无论你是AI新手还是AI专家,学习最前沿的AI技术,AI创富俱乐部你值得拥有!
本文由mdnice多平台发布
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。