对于查询的默认的锁
查询是一种很少可能干涉其他SQL语句的SQL语句因为查询基本上是只读数据。Insert ,update以及delete语句拥有隐式的查询作为这些语句的一部分。查询包括下面的各种语句:
Select
Insert ..select …;
Update ..;
Delete …;
不包括下面的语句:
Select …for update of…;
对于不带for update语句的所有的查询具有下面的正确的特征:
*一个查询不获取数据锁。因此,其他事务能够查询并且更新被查询的表,包括被查询指定的特定的行。因为没有for update语句的查询不会获取任何数据锁来阻塞其他操作,这样的查询在oracle 中经常被称为无阻塞查询。
*一个查询不会等待任何的数据锁被释放;查询总是可以进行。(查询在一些未决的分布式事务中可能不得不等待数据锁。)
对于insert ,update,delete以及select …for update语句的默认锁
对于insert ,update,delete以及select …for update语句的默认锁的特征如下:
*包含一个DML语句的事务通过语句获取对被修改行上的排外行锁。其他事务不能够更新或者删除被锁的行直到该锁事务或者提交或者回滚掉;
*包含一个DML语句的事务不需要对一个子查询或者一个隐式查询比如:在where条件中的一个查询中所筛选出来的行获取行锁。在DML语句中的一个子查询或者隐式查询是被保证和查询开始的情况保持一致的,并且看不见查询语句所属于的DML语句的效果。
*在一个事务中的一个查询可以看见在同一个事务中先前DML所做的变更信息。但是不会看见在它事务本身之后的其他事务开始所做的变更。
*除了必要的排外行锁,一个包含DML语句的事务在那些包含受影响行的表上获取至少一个行排外表锁。如果这个包含DML的事务已经占有对那张表的一个共享,共享行排外,或者排外表锁,那么这个行排外表锁将不会被获取。如果包含DML的事务已经拥有一个行共享表锁,那么oralce将会自动地将这种锁转换为一个行排外表锁。
DDL锁
当一个用户对象被操作或者被一个正在进行的DDL操作所引用时一个数据字典(DDL)锁是用来保护用户对象的定义。重新调用DDL语句会隐式地提交事务。例如:假设一个用户创建一个存储过程。代表该用户的单独的事务,oralce自动地为该存储过程定义中所引用的所有对象获取DDL锁。DDL锁是为了在该存储过程被完全编译完成之前阻止在存储过程中被引用的对象被修改或者被删除。
Oracle代表任何DDL事务所要求的自动地获取一个数据字典锁。用户不能够显式地请求DDL锁。只有被修改的或者被引用的单独的用户对象在DDL操作过程中被锁住。整个的数据字典从来不被锁住。
DDL锁分成三类:排外DDL锁,共享DDL锁以及可解除的解析锁。
排外DDL锁
大多数DDL操作,除了上面部分列出的DDL锁以外,共享DDL锁需要一个资源的排外DDL锁来阻止其他可能修改或者引用同一用户对象DDL操作带来的破坏性的干涉。例如:在当一个修改表的操作正在给表加一列时一个删除表的操作是不允许的,并且反之亦然。
在一个排外DDL锁获取的过程中,如果另一个对用户对象的DDL锁已经被另一个操作所占有,这样排外DDL锁将等待直到老的DDL锁被释放然后才进行下去。
DDL操作对将要修改的对象也获取DML锁(数据锁)。
共享DDL锁
一些DDL操作需要一个资源的共享DDL锁来阻止相冲突的DDL操作的破坏性干涉,但是允许类似的DDL操作的数据并发。例如:当一个create procedure语句正在运行,包含的事务对所有被引用的表获取共享DDL锁。其他事务也能够并发地创建一个也同时引用相同的表的存储过程并且因此也并发地获取了对相同表上的共享DDL锁,但是不允许事务在这些被引用的表中的任何一个上获取排外锁。也不允许事务修改或者删除一个被引用的表。结果,一个拥有一个共享DDL锁的事务保证了被引用的用户对象的定义将在事务进行的过程中保持不变。
因为下面的DDL语句关于一个对象的一个共享DDL锁将被获取:AUDIT,NOAUDIT,COMMENT,CRAETE [OR REPLACE] VIEW/PROCEDURE/PACKAGE/PACKAGE BODY/FUNCTION/TRIGGER,CREATE SYNONYM以及CREATE TABLE(当CLUSTER参数不被包含时)。
可解除的解析锁
在共享池中的一个SQL语句(或者PL/SQL程序单元)拥有SQL语句中所引用的每个对象的解析锁。解析锁被获取以便当一个被引用的对象被修改或者删除时,相关的共享SQL语句区域能够被设置为无效。一个解析锁不会不允许任何DDL操作并且允许将解析锁解除来允许相冲突的DDL操作,因此命名为可解除的解析锁。
一个解析锁在SQL语句执行的解析阶段被获取并且只要共享池中保存着该语句的共享SQL区域那么这个解析锁就被一直占用着。
DDL锁的持续时间
DDL锁的持续时间依据DDL锁的类型。排外的和共享的DDL锁在DDL语句执行的过程中一直持续着并且自动提交。一个解析锁是只要相关的SQL语句保存在共享池中就一直持有着。
DDL锁以及簇
在一个簇上的一个DDL操作获取在该簇中的簇和所有的表以及物化视图上的所有的排外的DDL锁。在一个簇中的一个表或者物化视图上的一个DDL操作获取了关于该簇的共享锁,除此之外,也获得对表或者物化视图上的一个共享锁或者排外DDL锁。对该簇的共享DDL锁阻止了在当第一个操作进行时其他的操作对该簇的删除操作的发生。
闩锁和内部锁
闩锁和内部锁保护了内部的数据库和内存结构。闩锁和内部锁对于用户来说似乎不可以访问的,因为用户不需要控制这两种锁的发生和持续时间。下面的部分将帮助来说明企业管理器锁和闩锁的监控器。
闩锁
闩锁是在SGA中的用来保护共享数据结构的一个简单的,低层的串行化机制。例如:闩锁保护当前访问数据库的用户的列表以及保护描述在缓冲区中数据块的数据结构。一个服务和后台进程在当操纵或者查看这些结构中的一个时需要获取一个持续一小段时间的闩锁。闩锁的执行情况是由操作系统决定的,特别是关于是否一个进程需要等待闩锁以及要等待多长时间的问题。
内部锁
内部锁是一个高层的,比闩锁更加复杂的机制并且为各种目的服务。
字典缓存锁
这些锁持续非常短的时间并且当数据字典中的项被修改或者被使用时对于该项的字典缓存锁将在字典缓存中被持有。它们保证被解析的语句不会与对象的定义不一致。
字典缓存锁可以是被共享的或者是排外的。共享锁是当解析被完成时被释放。排外锁是在当DDL操作完成时被释放。
文件和日志管理锁
这些锁是保护各种文件的。例如:一个锁保护控制文件以便一次只有一个进程能够修改控制文件。另一个锁协调重做日志文件的使用和归档。数据文件被锁住是为了确保多个实例是在一个共享模式下加载一个数据库的或者是确保一个实例在排外模式下加载数据库。因为文件和日志锁说明文件的状态,这些锁在必要的时候会持续很长时间。
表空间和回滚段锁
这些缩是为了保护表空间和回滚段。例如:所有访问数据库的实例必须对一个表空间是联机还是脱机的问题达成一致。回滚段被锁是以便只有一个实例可以对这个段进行写操作。
显式(手动)数据锁
Oracle总是自动地执行加锁来确保数据一致性,数据完整性,以及语句级别的读一致。但是,你能够覆盖oracle默认的锁机制。覆盖默认的锁在下面这些情形下是有用的:
*应用程序需要事务级别的读一致或者可重复读。换句话说,在在事务中的查询必须要在事务的持续过程中产生一致的数据,不反映其他事务的改变。你可以通过使用手动加锁,只读事务,串行化事务或者通过覆盖默认的锁的方式来是实现事务级别的读一致。
*应用程序需要一个事务拥有对一个资源的排外访问以便该事务不需要等待其他事务完成。
Oracle的自动锁可以是在事务级别或者会话级别上被覆盖。
在事务级别上,包含下面SQL语句的事务会覆盖oracle的默认的锁:
*set transaction isolation level语句;
*lock table语句(该语句可以锁一张表,当使用视图时,也可以锁视图的基表);
*select ..for update语句;
通过上面的语句所获取到的锁是在事务提交或者事务回滚之后被释放。
在会话级别上,一个会话可以使用带有alter system的语句来设置需要的事务隔离级别。
注意:如果oracle的默认锁在任何级别上被覆盖,数据库管理员或者应用程序开发者应该确保覆盖掉锁的过程正确地操作。这个加锁的过程必须满足下面的标准:数据完整性需要保证,数据一致性是可接受的,并且死锁是不可能发生的或者被适当处理。
Oracle锁管理服务
拥有oracle的锁管理,一个应用程序开发者在PL/SQL块中能够包括下面的语句:
*请求一个特定类型的锁;
*给予锁一个在同一个实例中或者在另一个实例中的另一个存储过程中可识别的唯一的名字;
*改变锁的类型;
*释放锁;
因为一个被保留的锁是和一个oracle锁是一样的,它拥有所有oracle锁的功能包括死锁检测。用户锁从来不会和oracle锁有冲突,因为用户锁带有UL前缀来识别的。
Oracle锁管理服务是通过在DBMS_LOCK包中的存储过程来实现的。
Oracle的回闪查询的概述
Oracle的回闪查询让你查看和补救历史数据。你可以执行数据库在一定的时间点之内的查询或者数据库在用户指定的系统变更号(SCN)上的查询。
回闪查询使用oracle的多版本读一致能力并且通过根据需要应用UNDO来恢复数据。Oracle数据库10g自动地优化一个叫undo retention的周期参数。这个undo retention的周期参数说明在老的UNDO信息(即已经被提交的事务的UNDO信息)被覆盖之前必须经过的时间数量。数据库收集是使用统计信息并且基于这些统计信息和基于UNDO表空间的大小来优化undo retention的周期参数值。
回闪查询使用oracle的多版本读一致能力并且通过根据需要应用UNDO来恢复数据。Oracle数据库10g自动地优化一个叫undo retention的周期参数。这个undo retention的周期参数说明在老的UNDO信息(即已经被提交的事务的UNDO信息)被覆盖之前必须经过的时间数量。数据库收集是使用统计信息并且基于这些统计信息和基于UNDO表空间的大小来优化undo retention的周期参数值。
使用回闪查询,你可以查询到今天早上,昨天或者是上一周的数据库信息。这种操作的速度只依赖于被查询出来的数据量以及需要被收回的数据上的变化的数量。
你可以查询指定行或者指定一个事务的历史。使用存储在数据库中的UNDO数据,你可以查看一行记录的所有的版本并且将该行转变为前一个版本。回闪事务查询历史让你在事务级别上来检查在数据库上的变化。
你可以审计一张表的行并且得到关于改变行的事务的信息以及当行被改变时的时间点的信息。通过事务ID,你能够通过使用LogMiner工具来做事务挖掘来得到完整的关于该事务的信息。
你可以设置你想查看的数据和时间点。然后,任何你运行的SQL语句查询将会是在你指定的时间点上的原数据上操作。如果你是一个被授权的用户,然后你能够纠正错误并且可以不需要管理员的干涉就可以收回恢复的数据。
带有as of SQL语句,你可以在一个查询中为每张表选择不同的快照。与一张表有关的一个快照被大家称为表装饰品。如果你没有使用快照来装饰一张表,然后一个默认的快照将会使用。所有没有指定快照的表将得到同样的默认的快照。
例如:假设你想写一个查询来得到在过去四小时中创建的所有新客户帐号。你可以使用不同as of短语来装饰同一张表的两种不同的情况设置操作。
DML和DDL操作能够使用表装饰来在子查询中选择快照。象insert table as select和create table as select的操作可以在子查询中使用表装饰来修理那些已经错误地被删除一些行的表。表装饰可以有任意的表达式:一个绑定变量,一个常量,一个字符串,数据操作等等。你可以打开一个游标并且动态地绑定一个快照值(一个时间点或者一个SCN)来装饰一张表。
回闪查询的优势
这部分列出使用回闪查询的好处:
*对应用程序透明
象报表生成工具一样的只做数据库查询操作类似的被打包的应用程序,可以通过使用登入触发器来使应用程序运行在回闪查询模式下。应用程序可以不需要对代码修改就可以透明地运行。应用程序需要被满足的所有约束被保证保存地很好,因为到回闪查询时间点为止有与数据库一致的版本。
*提高应用程序的性能
如果一个一个应用程序需要恢复活动,应用程序可以通过保存SCNs并且将数据库回闪到这些SCNs点上来完成恢复操作。这个比保存数据集和之后恢复着这些数据集更加地简单和更加快,因为保存数据集和之后恢复着这些数据集需要应用程序做显式地版本管理工作。使用回闪查询,对于显式地管理版本带来的重做日志的开销的成本将不会有。
*联机操作
回闪查询是一个联机操作,当一个对象在回闪查询中被查询时,那么来自其他的会话的并发的DMLs和查询操作也是允许的。这些操作的速度是不受影响的。此外,不同的会话对于同一个对象能够并发地回闪到不同的回闪时间点上或者回闪到指定的SCNs上。回闪查询自身的速度依赖于需要应用的UNDO的数量,UNDO的数量与回闪到指定的时间点的时间是成比例的。
*管理简单
在用户方面不需要额外的管理,除了设置适当的保存周期,有正确的权限等等。也不需要额外的重做日志管理,因为过去的版本是根据需要自动的建立起来的。
注意:*回闪查询不做任何撤消动作。这只是一个查询机制。你能够从一个回闪查询中获取输出然后在许多环境下你自己执行撤消动作;
*回闪不会告诉你什么变化了。但是LogMiner会告诉你;
*如果你知道需要及时返回原来的数据行的话使用回闪查询可以撤消变更并且是非常有效率的。你可以使用回闪来使一张表的全部回到原来的样子,但是如果这张表很大的话这个操作成本是很高的因为它需要对整张表做备份;
*对于象修改表列,或者删除表或者删除表中的数据这样的DDL操作使用回闪查询是无效的;
*LongMiner是获取变更的历史数据是很好的工具,但是LongMiner是以修改的操作形式(insert,update,delete)来记录历史变化的,而不是记录一行的修改前后的数据的方式来记录历史变化的。这些对于一些应用程序来说处理起来是困难的;
回闪查询的使用
下面列出了一些使用回闪查询的方法:
*自我修复
可能你意外地从表中删除了一些重要的行并且想恢复这些被删除的行数据。为了做这个修复工作,你可以立即向上追溯并且看到丢失的行然后重新将这些被删除的行插入到当前的表中;
*电子邮件和语音邮件应用
你可能删除了过去的邮件。使用回闪查询,你可以通过立即追溯来恢复被删除的邮件并且重新将被删除的邮件插入到当前的邮箱中去;
*账目结算
你可以查看到一个月内的某一天为止帐目结算之前的所有的帐目信息;
*已经打包的应用程序
已经打包的应用程序(象报表生成工具)能够不需要对应用程序的任何逻辑的修改而能够使用回闪查询。应用程序期待的任何约束被保证是满足要求的,因为用户看到的是指定时间点上或者指定的SCN上的数据库的一致的版本。
此外,回闪查询也可以在审计检查之后被使用来观看数据的前镜象。在数据分析系统(DSS)环境中,从联机事务系统(OLTP)中回闪查询是用来抽取在一个时间点上的一致的数据。