Oracle数据库的事务日志怎么理解


今天小编给大家分享一下Oracle数据库的事务日志怎么理解的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。redo重做日志文件(redo log file)对Oracle数据库来说至关重要,它们是数据库的事务日志。Oracle维护着两类重做日志文件:在线(online)重做日志文件和归档(archived)重做日志文件。这两类重做日志文件都用于恢复;其主要目的是,万一实例失败或介质失败,它们就能派上用场。如果数据库所在主机掉电,导致实例失败,Oracle会使用在线重做日志将系统恰好恢复到掉电之前的那个时间点。如果磁盘驱动器出现故障(这是一个介质失败),Oracle会使用归档重做日志以及在线重做日志将该驱动器上的数据备份恢复到适当的时间点。归档重做日志文件实际上就是已填满的”旧”在线重做日志文件的副本。系统将日志文件填满时,ARCH进程会在另一个位置建立在线重做日志文件的一个副本,也可以在本地和远程位置上建立多个另外的副本.如果由于磁盘驱动器损坏或者其他物理故障而导致失败,就会用这些归档重做日志文件来执行介质恢复.Oracle拿到这些归档重做日志文件,并把它们应用于数据文件的备份,使这些数据文件能与数据库的其余部分保持一至.归档重做日志文件是数据库的事务历史。测量redoredo管理是数据库中的一个串行点.任何Oracle实例都有一个LGWR,最终所有事务都会归于LGWR,要求这个进程管理它们的redo,并COMMIT其事务,LGWR工作越忙,系统就会越慢.通过查看一个操作会生成多少redo,并对一个问题的多种解决方法进行测试,可以从中找出最佳的方法。与redo有关的视图V$MYSTAT,其中有会话的提交信息V$STATNAME,这个视图能告诉我们V$MYSTAT中的每一行表示什么(查看的统计名)。查询redo大小的语句SELECT a.NAME,b.VALUE cur_size_byte,round(b.VALUE / 1024, 3) || ‘KB’ cur_size_kbFROM v$statname a, v$mystat bWHERE a.statistic# = b.statistic#AND lower(a.NAME) LIKE ‘%’ || lower(‘redo size’) || ‘%’数据库归档模式数据库归档用来保存redo的日志文件副本,一般安装时默认未开启数据库的归档模式。在NOARCHIVELOG模式的数据库中,除了数据字典的修改外,CREATE TABLE不会记录日志.如果你想在NOARCHIVELOG模式的数据库上看到差别,可以把对表T的DROP TABLE和CREATE TABLE换成DROP INDEX和CREATE INDEX。默认情况下,不论数据库以何种模式运行,这些操作都会生成日志。因为不同的模式可能导致不同的行为。你的生产系统可能采用ARCHIVELOG模式运行.倘若你执行的大量操作在ARCHIVELOG模式下会生成redo,而在NOARCHIVELOG模式下不会生成redo,你肯定想在测试时就发现这一点,而不要等到系统交付给用户时才暴露出来!查看是否归档查看数据库是否开启归档select name,log_mode from v$database;启用归档startup mountalter database archivelog;alter database open;禁止归档shutdown immediatestartup mountalter database noarchivelogalter database openforce logging(强制日志)模式:如果数据库强制日志模式开启后,则Oracle无论什么操作都进行redo的写入。查看强制日志模式通过select force_logging from v$database可以看到当前数据库是否开启了强制日志模式状态开启强制日志模式如果未开启数据库强制日志模式(默认未开启),则可以通过alter database force logging开启,之后Oracle无论什么操作都进行redo的写入,不依赖于数据库的归档模式等其他因素.关闭强制日志模式如果已经开启了数据库强制日志模式,则可以通过alter database no force logging关闭强制日志模式。使数据库恢复先前的设置,数据库是否写入redo由数据库的归档模式等其他因素决定disable_logging那么在Oracle内部还存在一个内部参数:_disable_logging 默认是false通过更改为true可以让Oracle在修改表中的记录的时候完全不记录redo,这个参数要甚用,平时,我们只作为性能测试用。查看:show parameter disa /disable/_disable_logging开启:alter system set “_disable_logging”=true scope=both;禁用:alter system set “_disable_logging”=false表的归档模式查看表的logging模式查看表是否是logging状态用如下SQL:select table_name,logging from dba_tables where table_name=’tablename’;修改表的logging模式修改表的logging状态sql:alter table table_name nologging/logging减少redo写入本节所讲的都是当数据库未开启强制日志模式时的操作。对象的操作在执行时会产生重做日志,采用某种方式,生成的redo会比平常(即不使用NOLOGGING子句时)少得多.注意,这里说”redo”少得多,而不是”完全没有redo”.所有操作都会生成一些redo,不论数据库的日志模式是什么,所有数据字典操作都会计入日志。如何减少redocreate table时减少redo的方法创建表时crate table as加入nolongging选项减少redo,格式如下create table [table_name] nologging as [select表达式]。insert into减少redo的方法insert 大批量数据时加入/*+append */选项减少redo写入,格式如下insert /*+append */ into [table_name] [select表达式]数据库归档模式下生成redo规则create table时nologging效果归档模式下创建的表,默认为logging模式。创建表时crate table as加入nolongging选项减少redo写入明显验证下面比较以下两种create table as时产生的redo size量。SELECT a.NAME,b.VALUE cur_size_byte,round(b.VALUE / 1024, 3) || ‘KB’ cur_size_kbFROM v$statname a, v$mystat bWHERE a.statistic# = b.statistic#AND lower(a.NAME) LIKE ‘%’ || lower(‘redo size’) || ‘%’查询当前的重做日志大小记录下来create table test_1 as select * from test;SELECT a.NAME,b.VALUE cur_size_byte,round(b.VALUE / 1024, 3) || ‘KB’ cur_size_kbFROM v$statname a, v$mystat bWHERE a.statistic# = b.statistic#AND lower(a.NAME) LIKE ‘%’ || lower(‘redo size’) || ‘%’查询当前的重做日志大小减去前面记录下来的值计算刚才这个操作产生的redo大小标记为redo_1SELECT a.NAME,b.VALUE cur_size_byte,round(b.VALUE / 1024, 3) || ‘KB’ cur_size_kbFROM v$statname a, v$mystat bWHERE a.statistic# = b.statistic#AND lower(a.NAME) LIKE ‘%’ || lower(‘redo size’) || ‘%’查询当前的重做日志大小记录下来create table test_2 nologging as select * from test;SELECT a.NAME,b.VALUE cur_size_byte,round(b.VALUE / 1024, 3) || ‘KB’ cur_size_kbFROM v$statname a, v$mystat bWHERE a.statistic# = b.statistic#AND lower(a.NAME) LIKE ‘%’ || lower(‘redo size’) || ‘%’查询当前的重做日志大小减去前面记录下来的值计算刚才这个操作产生的redo大小标记为redo_2比较redo_1和redo_2的大小就知道crate table as加入nolongging或不加nologging选项的区别了insert into时加入append效果表模式logging当表模式为logging状态时,无论是append模式还是no append模式,redo都会生成,即加入append选项无法生效。验证下面比较以下两种insert时产生的redo size量,可以看出redo量是差不多的。计算重做大小的方法与上面的一样就不说了1、insert /*+append */ into test_1 select * from test;commit;2、insert into test_1 select * from test;commit;表模式nologging当表模式为nologging状态时,只有加入append模式会明显减少生成redo。验证1、insert /*+append */ into test_1 select * from test;commit;2、insert into test_1 select * from test;commit;数据库非归档模式生成redo规则create table 使用nologging对产生redo的影响非归档模式下创建的表,默认为nologging模式。在NOARCHIVELOG模式的数据库中,除了数据字典的修改外,CREATE TABLE不会记录日志。因此创建表时(crate table as)加入nologging选项减少redo写入不明显,即nologging选项加不加都差不多验证下面比较以下两种create table as时产生的redo size量。create table test_1 as select * from test;create table test_2 nologging as select * from test;insert into时append效果表模式logging当表模式为logging状态时,加入append模式明显减少生成redo,而no append模式下不会减少生成。验证insert /*+append */ into test_1 select * from test;commit;insert into test_1 select * from test;commit;表模式nologging当表模式为nologging状态时,append的模式会减少生成redo,而no append模式不会减少生成。验证insert /*+append */ into test_1 select * from test;commit;insert into test_1 select * from test;commit;其实就是直截加载与传统加载的区别
直接加载优势直接加载比传统加载效率要高不扫描原来的空数据块不需要sql解析,减少系统的负载不经过SGA不走DBWR进程,走自己的专属进程,所以速度快直接加载限制不能加载簇表锁定整个表,在表上有活动事务的时候不能加载直接加载特点直接加载是在所有数据块后面加载新数据块,修改高水位线,不扫描原来的空数据块。直接加载只产生一点点的管理redo,因为要修改数据字典(也可以讲不产生redo)。回滚,如果加载失败把新分配数据块抹掉就行了。无需SGA,无需SQL解析,无需DBWR进程实验现在我们已经定义了test;SQL> select count(*) from test; 现在表里没有记录数 COUNT(*)———- 0SQL> select segment_name,extent_id,bytes from user_extents where segment_name=’TEST’; 现在分配了1个区SEGMENT_NAME EXTENT_ID BYTES——————————————————————————– ———- ———-TEST 0 65536[oracle@secdb1 ~]$ sqlldr userid=ls/ls control=leo_test.ctl data=leo_test.data log=leo_test.log 传统方式加载数据LS@LEO> select count(*) from test; 已经成功加载了100万条数据 COUNT(*)———- 1000000SQL> select segment_name,extent_id,bytes from user_extents where segment_name=’TEST’; 100万条数据占用28个区SEGMENT_NAME EXTENT_ID BYTES——————————————————————————– ———- ———-TEST 0 65536TEST 1 65536TEST 2 65536TEST 3 65536TEST 4 65536TEST 5 65536TEST 6 65536TEST 7 65536TEST 8 65536TEST 9 65536TEST 10 65536TEST 11 65536TEST 12 65536TEST 13 65536TEST 14 65536TEST 15 65536TEST 16 1048576TEST 17 1048576TEST 18 1048576TEST 19 1048576SEGMENT_NAME EXTENT_ID BYTES——————————————————————————– ———- ———-TEST 20 1048576TEST 21 1048576TEST 22 1048576TEST 23 1048576TEST 24 1048576TEST 25 1048576TEST 26 1048576TEST 27 104857628 rows selectedSQL> delete from test; 删除100万条数据1000000 rows deleted.SQL> commit; 提交Commit complete.SQL> select segment_name,extent_id,bytes from user_extents where segment_name=’TEST’;SEGMENT_NAME EXTENT_ID BYTES——————————————————————————– ———- ———-TEST 0 65536TEST 1 65536TEST 2 65536TEST 3 65536TEST 4 65536TEST 5 65536TEST 6 65536TEST 7 65536TEST 8 65536TEST 9 65536TEST 10 65536TEST 11 65536TEST 12 65536TEST 13 65536TEST 14 65536TEST 15 65536TEST 16 1048576TEST 17 1048576TEST 18 1048576TEST 19 1048576SEGMENT_NAME EXTENT_ID BYTES——————————————————————————– ———- ———-TEST 20 1048576TEST 21 1048576TEST 22 1048576TEST 23 1048576TEST 24 1048576TEST 25 1048576TEST 26 1048576TEST 27 104857628 rows selected把数据都删除了还占用空间,oracle的delete操作不回收空间,只是把自己的记录标记为删除,实际呢还占用的空间不释放[oracle@secdb1 ~]$ sqlldr userid=ls/ls control=leo_test.ctl data=leo_test.data log=leo_test.log 第二次传统方式加载数据SQL> select count(*) from test; 已经成功加载了100万条数据 COUNT(*)———- 1000000SQL> select segment_name,extent_id,bytes from user_extents where segment_name=’TEST’;SEGMENT_NAME EXTENT_ID BYTES——————————————————————————– ———- ———-TEST 0 65536TEST 1 65536TEST 2 65536TEST 3 65536TEST 4 65536TEST 5 65536TEST 6 65536TEST 7 65536TEST 8 65536TEST 9 65536TEST 10 65536TEST 11 65536TEST 12 65536TEST 13 65536TEST 14 65536TEST 15 65536TEST 16 1048576TEST 17 1048576TEST 18 1048576TEST 19 1048576SEGMENT_NAME EXTENT_ID BYTES——————————————————————————– ———- ———-TEST 20 1048576TEST 21 1048576TEST 22 1048576TEST 23 1048576TEST 24 1048576TEST 25 1048576TEST 26 1048576TEST 27 104857628 rows selected使用传统方式加载数据,会扫描原来的空数据块,会把新加载的数据插入到空数据块内,看我们还是使用原来的28个区SQL> delete from test; 这是第二次删除100万条数据1000000 rows deleted.SQL> commit; 提交Commit complete.SQL> select segment_name,extent_id,bytes from user_extents where segment_name=’TEST’;SEGMENT_NAME EXTENT_ID BYTES——————————————————————————– ———- ———-TEST 0 65536TEST 1 65536TEST 2 65536TEST 3 65536TEST 4 65536TEST 5 65536TEST 6 65536TEST 7 65536TEST 8 65536TEST 9 65536TEST 10 65536TEST 11 65536TEST 12 65536TEST 13 65536TEST 14 65536TEST 15 65536TEST 16 1048576TEST 17 1048576TEST 18 1048576TEST 19 1048576SEGMENT_NAME EXTENT_ID BYTES——————————————————————————– ———- ———-TEST 20 1048576TEST 21 1048576TEST 22 1048576TEST 23 1048576TEST 24 1048576TEST 25 1048576TEST 26 1048576TEST 27 104857628 rows selecteddelete还是不回收空间,我们依然占用着28个区[oracle@secdb1 ~]$ sqlldr userid=ls/ls control=leo_test.ctl data=leo_test.data log=leo_test.log direct=true 直接方式加载数据SQL> select segment_name,extent_id,bytes from user_extents where segment_name=’TEST’;SEGMENT_NAME EXTENT_ID BYTES——————————————————————————– ———- ———-TEST 0 65536TEST 1 65536TEST 2 65536TEST 3 65536TEST 4 65536TEST 5 65536TEST 6 65536TEST 7 65536TEST 8 65536TEST 9 65536TEST 10 65536TEST 11 65536TEST 12 65536TEST 13 65536TEST 14 65536TEST 15 65536TEST 16 1048576TEST 17 1048576TEST 18 1048576TEST 19 1048576SEGMENT_NAME EXTENT_ID BYTES——————————————————————————– ———- ———-TEST 20 1048576TEST 21 1048576TEST 22 1048576TEST 23 1048576TEST 24 1048576TEST 25 1048576TEST 26 1048576TEST 27 1048576TEST 28 1048576TEST 29 1048576TEST 30 1048576TEST 31 1048576TEST 32 1048576TEST 33 1048576TEST 34 1048576TEST 35 1048576TEST 36 1048576TEST 37 1048576TEST 38 1048576TEST 39 1048576TEST 40 1048576TEST 41 1048576TEST 42 1048576TEST 43 1048576TEST 44 1048576TEST 45 1048576TEST 46 1048576TEST 47 104857648 rows selected发现同样的100万条记录,竟然占用了48个区,传统加载只用了28个,而我们使用直接加载到多了20个数据块,对了直接加载不扫描原来的空数据块,会在所有数据块之后加载新的数据块插入数据修改高水位线HWM,当提交事务之后,把高水位线移到新数据之后,其他的用户就可以看见了。比较直接加载使用conventional 和direct方式产生的redo大小(可以通过/*+ append */模拟直接加载)。明确:直接加载与logging配合下并不能显著的减少redo日志量 直接加载与nologging配合下可以大幅度的减少redo日志量SQL> create table leo_t1 as select * from test where 1=2; 创建leo_t1表Table created.SQL> alter table leo_t1 logging; 设置leo_t1表logging模式Table altered.SQL> set autotrace traceonly;SQL> insert into leo_t1 select * from leo_test_sqlload where rownum
20000 rows created.Statistics 统计信息———————————————————- 1071 recursive calls 2668 db block gets 1860 consistent gets 386 physical reads 1680404 redo size 这是产生的日志量1680404 680 bytes sent via SQL*Net to client 603 bytes received via SQL*Net from client 4 SQL*Net roundtrips to/from client 6 sorts (memory) 0 sorts (disk) 20000 rows processedSQL> rollback; 回滚操作,使用undo表空间Rollback complete.SQL> insert /*+ append */ into leo_t1 select * from leo_test_sqlload where rownum
20000 rows created.Statistics———————————————————- 94 recursive calls 268 db block gets 1294 consistent gets 202 physical reads 1627260 redo size 当leo_t1为logging属性时,直接加载和传统加载产生redo日志差不多 664 bytes sent via SQL*Net to client 617 bytes received via SQL*Net from client 4 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 20000 rows processed小结:这是因为在logging模式下,所有的数据块的改变都会产生redo日志,为以后恢复做准备,这时候直接加载没有多大的优势。直接加载与nologging配合下可以大幅度的减少redo日志量重大前提如果你的数据库开启了force_logging=yes模式,那么不管你是传统加载还是直接加载都不会减少redo产生量所以要想大幅度减少redo日志就必须满足3个条件(1)关闭force_logging选项 alter database no force logging; 启动 alter database force logging;(2)数据对象级别nologging模式 alter table leo_t1 nologging;(3)直接加载 insert /*+ append */ into数据库归档与redo日志量关系数据库处于归档模式 当表模式为logging状态时,无论是否使用append模式,都会生成redo.当表模式为nologging状态时,只有a开发云主机域名ppend模式,不会生成redo。数据库处于非归档模式 无论是在logging还是nologing的模式下,append的模式都不会生成redo,而no append模式下都会生成redo。SQL> alter database no force logging; SQL> select force_logging from v$database; 已经关闭force_logging选项FOR—NOSQL> alter table leo_t1 nologging; 设置leo_t1表nologging模式Table altered.SQL> select logging from user_tables where table_name=’LEO_T1′;LOG—NOSQL> select count(*) from leo_t1; 0条记录 COUNT(*)———- 0SQL> select index_name from user_indexes where table_name=’LEO_T1′; 表上没有索引no rows selectedSQL> insert /*+ append */ into leo_t1 select * from leo_test_sqlload where rownum
20000 rows created.Statistics———————————————————- 1443 recursive calls 649 db block gets 1702 consistent gets 1519 physical reads 44900 redo size 直接加载产生的redo日志非常少 658 bytes sent via SQL*Net to client 617 bytes received via SQL*Net from client 开发云主机域名 4 SQL*Net roundtrips to/from client 9 sorts (memory) 0 sorts (disk) 20000 rows processedSQL> rollback;Rollback complete.LS@LEO> insert into leo_t1 select * from leo_test_sqlload where rownum
20000 rows created.Statistics———————————————————- 4 recursive calls 2207 db block gets 1534 consistent gets 441 physical reads 1634064 redo size 传统加载产生的redo日志非常非常的多 673 bytes sent via SQL*Net to client 603 bytes received via SQL*Net 开发云主机域名from client 4 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 20000 rows processed小结:直接加载与nologging配合下可以大幅度的减少redo日志量,因为插入的数据不产生redo日志,所以在插入后要做备份操作,一旦数据损坏,就要使用备份来恢复,不能使用redo来恢复。注意要关闭force_logging选项以上就是“Oracle数据库的事务日志怎么理解”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注开发云行业资讯频道。

相关推荐: 如何使用Linux系统高效数据统计工具wc命令

本篇文章为大家展示了如何使用Linux系统高效数据统计工具wc命令,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。主要参数常见参数如下:-c 统计字节数。-l 统计行数。-m 统计字符数。这个标志不能与 -c 标志一起使…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 03/29 15:03
下一篇 03/29 15:03

相关推荐