锁是数据库中的一个非帔R要的概念Q它主要用于多用L境下保证数据库完整性和一致性?我们知道Q多个用戯够同时操U同一个数据库中的数据Q会发生数据不一致现象。即如果没有锁定且多个用户同时访问一个数据库Q则当他们的事务同时使用相同的数据时可能会发生问题。这些问题包括:丢失更新、脏诅R不可重复读和觉读Q?br>1Q当两个或多个事务选择同一行,然后Z最初选定的值更新该行时Q会发生丢失更新问题。每个事务都不知道其它事务的存在。最后的更新重写由其它事务所做的更新Q这导致数据丢失。例如,两个~辑人员制作了同一文档的电子复本。每个编辑h员独立地更改其复本,然后保存更改后的复本Q这样就覆盖了原始文档。最后保存其更改复本的编辑h员覆盖了W一个编辑h员所做的更改。如果在W一个编辑h员完成之后第二个~辑人员才能q行更改Q则可以避免该问题?br>2. 脏读是指当一个事务正在访问数据,q且Ҏ据进行了修改Q而这U修改还没有提交到数据库中,q时Q另外一个事务也讉Kq个数据Q然后用了q个数据。因个数据是q没有提交的数据Q那么另外一个事务读到的q个数据是脏数据Q依据脏数据所做的操作可能是不正确的。例如,一个编辑h员正在更改电子文档。在更改q程中,另一个编辑h员复制了该文档(该复本包含到目前为止所做的全部更改Qƈ其分发l预期的用户。此后,W一个编辑h员认为目前所做的更改是错误的Q于是删除了所做的~辑q保存了文档。分发给用户的文档包含不再存在的~辑内容Qƈ且这些编辑内容应认ؓ从未存在q。如果在W一个编辑h员确定最l更改前M人都不能d更改的文档,则可以避免该问题?br>3Q不可重复读是指在一个事务内Q多ơ读同一数据。在q个事务q没有结束时Q另外一个事务也讉K该同一数据。那么,在第一个事务中的两ơ读数据之间Q由于第二个事务的修改,那么W一个事务两ơ读到的的数据可能是不一L。这样就发生了在一个事务内两次d的数据是不一LQ因此称为是不可重复诅R例如,一个编辑h员两ơ读取同一文档Q但在两ơ读取之_作者重写了该文档。当~辑人员W二ơ读取文档时Q文档已更改。原始读取不可重复。如果只有在作者全部完成编写后~辑人员才可以读取文档,则可以避免该问题?br>4Q觉读是指当事务不是独立执行时发生的一U现象,例如W一个事务对一个表中的数据q行了修改,q种修改涉及到表中的全部数据行。同ӞW二个事务也修改q个表中的数据,q种修改是向表中插入一行新数据。那么,以后׃发生操作W一个事务的用户发现表中q有没有修改的数据行Q就好象发生了觉一栗例如,一个编辑h员更改作者提交的文档Q但当生产部门将其更改内容合q到该文档的d本时Q发C者已未~辑的新材料d到该文档中。如果在~辑人员和生产部门完成对原始文档的处理之前,M人都不能新材料d到文档中Q则可以避免该问题?br>所以,处理多用户ƈ发访问的Ҏ是加锁。锁是防止其他事务访问指定的资源控制、实现ƈ发控制的一U主要手Dc当一个用户锁住数据库中的某个对象Ӟ其他用户׃能再讉K该对象。加锁对q发讉K的媄响体现在锁的_度上。ؓ了控刉定的资源Q应该首先了解系l的I间理。在SQL Server 2000pȝ中,最的I间理单位是页Q一个页?K。所有的数据、日志、烦引都存放在页上。另外,使用|一个限Ӟq就是表中的一行数据必d同一个页上,不能跨页。页上面的空间管理单位是盘区Q一个盘区是8个连l的c表和烦引的最占用单位是盘区。数据库是由一个或者多个表或者烦引组成,x由多个盘区组成。放在一个表上的锁限制对整个表的q发讉KQ放在盘Z的锁限制了对整个盘区的访问;攑֜数据上的锁限制了对整个数据늚讉KQ放在行上的锁只限制对该行的q发讉K?/font>
SQL Server 2000 h多粒度锁定,允许一个事务锁定不同类型的的资源。ؓ了锁定的成本减x,SQL Server 自动资源锁定在适合d的别。锁定在较小的粒度(例如行)可以增加q发但需要较大的开销Q因为如果锁定了许多行,则需要控制更多的锁。锁定在较大的粒度(例如表)ƈ发而言是相当昂늚Q因为锁定整个表限制了其它事务对表中L部分q行讉KQ但要求的开销较低Q因为需要维护的锁较。SQL Server 可以锁定行、页、扩展盘区、表、库{资源?br>行是可以锁定的最空? 行锁占用的数据资源最,所以在事务的处理过E中Q允许其他事务l操U同一个表或者同一个页的其他数据,大大降低了其他事务等待处理的旉Q提高了pȝ的ƈ发性?br>锁是指在事务的操U过E中Q无Z务处理数据的多少Q每一ơ都锁定一,在这个页上的数据不能被其他事务操Uc在SQL Server 7.0以前Q用的是页U锁。页U锁锁定的资源比行锁锁定的数据资源多。在锁中Q即使是一个事务只操纵上的一行数据,那么该页上的其他数据行也不能被其他事务用。因此,当用页U锁Ӟ会出现数据的费现象Q也是_在同一个页上会出现数据被占用却没有使用的现象。在q种现象中,数据的浪Ҏ多不过一个页上的数据行?br>表锁也是一个非帔R要的锁。表U锁是指事务在操U|一个表的数据时Q锁定了q个数据所在的整个表,其他事务不能讉K该表中的其他数据。当事务处理的数据量比较大时Q一般用表U锁。表U锁的特Ҏ使用比较的pȝ资源Q但是却占用比较多的数据资源。与行锁和锁相比,表锁占用的pȝ资源例如内存比较,但是占用的数据资源却是最大。在表锁时Q有可能出现数据的大量浪费现象,因ؓ表锁锁定整个表Q那么其他的事务都不能操U表中的其他数据?br>盘区锁是一U特D类型的锁,只能用在一些特D的情况下。簇U锁是指事务占用一个盘区,q个盘区不能同时被其他事务占用。例如在创徏数据库和创徏表时Q系l分配物理空间时使用q种cd的锁。系l是按照盘区分配I间的。当pȝ分配I间Ӟ使用盘区锁,防止其他事务同时使用同一个盘区。当pȝ完成分配I间之后Q就不再使用q种cd的盘区锁。特别是Q当涉及到对数据操作的事务时Q不使用盘区锁?br>数据库锁是指锁定整个数据库Q防止Q何用h者事务对锁定的数据库q行讉K。数据库U锁是一U非常特D的锁,它只是用于数据库的恢复操作过E中。这U等U的锁是一U最高等U的锁,因ؓ它控制整个数据库的操作。只要对数据库进行恢复操作,那么需要设|数据库为单用户模式Q这Ll就能防止其他用户对该数据库q行各种操作?br>行锁是一U最优锁Q因U锁不可能出现数据既被占用又没有使用的浪费现象。但是,如果用户事务中频J对某个表中的多条记录操作,导致对该表的许多记录行都加上了行锁,数据库系l中锁的数目会急剧增加Q这样就加重了系l负P影响pȝ性能。因此,在SQL Server中,q支持锁升(lock escalation)。所谓锁升是指调整锁的_度Q将多个低粒度的锁替换成数的更高粒度的锁,以此来降低系l负荗在SQL Server中当一个事务中的锁较多Q达到锁升门限Ӟpȝ自动行U锁和页面锁升U锁。特别值得注意的是Q在SQL Server中,锁的升门限以及锁升U是ql自动来定的,不需要用戯|?br> 在SQL Server数据库中加锁Ӟ除了可以对不同的资源加锁Q还可以使用不同E度的加锁方式,即锁有多U模式,SQL Server中锁模式包括Q?nbsp; 1Q共享锁 SQL Server中,׃n锁用于所有的只读数据操作。共享锁是非独占的,允许多个q发事务d光定的资源。默认情况下Q数据被d后,SQL Server立即释放׃n锁。例如,执行查询“SELECT * FROM AUTHORS”Ӟ首先锁定W一,d之后Q释攑֯W一늚锁定Q然后锁定第二页。这P允许在L作过E中Q修Ҏ被锁定的W一c但是,事务隔离U别q接选项讄和SELECT语句中的锁定讄都可以改变SQL Server的这U默认设|。例如,“ SELECT * FROM AUTHORS HOLDLOCK”p求在整个查询q程中,保持对表的锁定,直到查询完成才释N定?nbsp; 2Q更新锁 更新锁在修改操作的初始化阶段用来锁定可能要被修改的资源,q样可以避免使用׃n锁造成的死锁现象。因Z用共享锁Ӟ修改数据的操作分Z步,首先获得一个共享锁Q读取数据,然后共享锁升为排它锁Q然后再执行修改操作。这样如果同时有两个或多个事务同时对一个事务申请了׃n锁,在修Ҏ据的时候,q些事务都要共享锁升为排它锁。这Ӟq些事务都不会释攑օ享锁而是一直等待对斚w放,q样造成了死锁。如果一个数据在修改前直接申h新锁Q在数据修改的时候再升为排它锁Q就可以避免死锁?br>3Q排它锁 排它锁是ZҎ据而保留的。它所锁定的资源,其他事务不能d也不能修攏V?nbsp; 4Q结构锁 执行表的数据定义语言 (DDL) 操作Q例如添加列或除去表Q时使用架构修改 (Sch-M) 锁。当~译查询Ӟ使用架构E_?(Sch-S) 锁。架构稳定?(Sch-S) 锁不dM事务锁,包括排它锁。因此在~译查询Ӟ其它事务Q包括在表上有排它锁的事务)都能l箋q行。但不能在表上执?DDL 操作?br>5Q意向锁 意向锁说明SQL Server有在资源的低层获得共享锁或排它锁的意向。例如,表的共享意向锁说明事务意图排它锁释放到表中的|者行。意向锁又可以分为共享意向锁、独占意向锁和共享式独占意向锁。共享意向锁说明事务意图在共享意向锁所锁定的低层资源上攄׃n锁来d数据。独占意向锁说明事务意图在共享意向锁所锁定的低层资源上攄排它锁来修改数据。共享式排它锁说明事务允许其他事务用共享锁来读取顶层资源,q意囑֜该资源低层上攄排它锁?nbsp; 6Q大定w更新?nbsp; 当将数据大容量复制到表,且指定了 TABLOCK 提示或者?sp_tableoption 讄?table lock on bulk 表选项Ӟ用大定w更新 锁。大定w更新锁允许进E将数据q发地大定w复制到同一表,同时防止其它不进行大定w复制数据的进E访问该表?br> SQL Serverpȝ中徏议让pȝ自动理锁,该系l会分析用户的SQL语句要求Q自动ؓ该请求加上合适的锁,而且在锁的数目太多时Q系l会自动q行锁升U。如前所qͼ升的门限由pȝ自动配置Qƈ不需要用户配|?在实际应用中Q有时ؓ了应用程序正运行和保持数据的一致性,必须Zؓ地给数据库的某个表加锁。比如,在某应用E序的一个事务操作中Q需要根据一~号对几个数据表做统计操作,Z证统计数据时间的一致性和正确性,从统计第一个表开始到全部表结束,其他应用E序或事务不能再对这几个表写入数据,q个时候,该应用程序希望在从统计第一个数据表开始或在整个事务开始时能够q序h为地Q显式地Q锁定这几个表,q就需要用到手工加锁(也称昑ּ加锁Q技术?br>可以使用 SELECT、INSERT、UPDATE ?DELETE 语句指定表锁定提示的范_以引?Microsoft SQL Server 2000 使用所需的锁cd。当需要对对象所获得锁类型进行更_控制Ӟ使用表锁定提示更改默认的锁定行为?br>所指定的表U锁定提C有如下几种Q?nbsp; 1Q?HOLDLOCK: 在该表上保持׃n锁,直到整个事务l束Q而不是在语句执行完立即释放所d的锁?nbsp; 2Q?NOLOCKQ不d׃n锁和排它锁,当这个选项生效后,可能d未提交读的数据或“脏数?#8221;Q这个选项仅仅应用于SELECT语句?nbsp; 3Q?PAGLOCKQ指定添加页锁(否则通常可能d表锁Q?nbsp; 4Q?READCOMMITTED用与q行在提交读隔离U别的事务相同的锁语义执行扫描。默认情况下QSQL Server 2000 在此隔离U别上操作。?nbsp; 5Q?READPAST: 跌已经加锁的数据行Q这个选项事务d数据时蟩q那些已l被其他事务锁定的数据行Q而不是阻塞直到其他事务释NQREADPAST仅仅应用于READ COMMITTED隔离性别下事务操作中的SELECT语句操作?nbsp; 6Q?READUNCOMMITTEDQ等同于NOLOCK?nbsp; 7Q?REPEATABLEREADQ设|事务ؓ可重复读隔离性别?nbsp; 8Q?ROWLOCKQ用行U锁Q而不使用_度更粗的页U锁和表U锁?nbsp; 9Q?SERIALIZABLEQ用与运行在可串行读隔离U别的事务相同的锁语义执行扫描。等同于 HOLDLOCK?nbsp; 10Q?TABLOCKQ指定用表U锁Q而不是用行U或面U的锁,SQL Server在该语句执行完后释放q个锁,而如果同时指定了HOLDLOCKQ该锁一直保持到q个事务l束?nbsp; 11Q?TABLOCKXQ指定在表上使用排它锁,q个锁可以阻止其他事务读或更新这个表的数据,直到q个语句或整个事务结束?nbsp; 12Q?UPDLOCK Q指定在读表中数据时讄更新 锁(update lockQ而不是设|共享锁Q该锁一直保持到q个语句或整个事务结束,使用UPDLOCK的作用是允许用户先读取数据(而且不阻塞其他用戯数据Q,q且保证在后来再更新数据Ӟq一D|间内q些数据没有被其他用户修攏V?nbsp; 死锁问题 在数据库pȝ中,死锁是指多个用户Q进E)分别锁定了一个资源,q又试图h锁定Ҏ已经锁定的资源,q就产生了一个锁定请求环Q导致多个用Pq程Q都处于{待Ҏ释放所锁定资源的状态。这U死锁是最典型的死锁Ş? 例如在同一旉内有两个事务A和BQ事务A有两个操作:锁定表part和请求访问表supplierQ事务B也有两个操作Q锁定表supplier和请求访问表part。结果,事务A和事务B之间发生了死锁?br> 死锁的第二种情况是,当在一个数据库中时Q有若干个长旉q行的事务执行ƈ行的操作Q当查询分析器处理一U非常复杂的查询例如q接查询Ӟ那么׃不能控制处理的顺序,有可能发生死锁现象?br> 在SQL Server中,pȝ能够自动定期搜烦和处理死锁问题。系l在每次搜烦中标识所有等待锁定请求的q程会话Q如果在下一ơ搜索中该被标识的进E仍处于{待状态,SQL Server开始递归死锁搜烦。当搜烦到锁定h环时QSQL Server 通过自动选择可以打破死锁的线E(死锁牺牲品)来结束死锁。SQL Server 回滚作ؓ死锁牺牲品的事务Q通知U程的应用程序(通过q回 1205 号错误信息)Q取消线E的当前hQ然后允怸间断U程的事务l进行。SQL Server 通常选择q行撤消时花Ҏ的事务的线E作为死锁牺牲品。另外,用户可以使用 SET 语句会话的 DEADLOCK_PRIORITY 讄?LOW。DEADLOCK_PRIORITY 选项控制在死锁情况下如何衡量会话的重要性。如果会话的讄?LOW Q则当会话陷入死锁情冉|成为首选牺牲品?br> 理解了死锁的概念Q在应用E序中就可以采用下面的一些方法来量避免死锁了: Q?Q合理安排表讉K序?Q?Q在事务中尽量避免用户干预,量使一个事务处理的d些, 保持事务短ƈ在一个批处理中?Q?Q数据访问时域离散法, 数据讉K时域L法是指在客户?服务器结构中Q采取各U控制手D|制对数据库或数据库中的对象访问时间段。主要通过以下方式实现: 合理安排后台事务的执行时_采用工作对后台事务q行l一理。工作流在管理Q务时Q一斚w限制同一cMQ务的U程敎ͼ往往限制?个)Q防止资源过多占? 另一斚w合理安排不同d执行时序、时_量避免多个后台d同时执行Q另外, 避免在前C易高峰时间运行后CQ务?Q?Q数据存储空间离散法。数据存储空间离散法是指采取各种手段Q将逻辑上在一个表中的数据分散到若q离散的I间上去Q以便改善对表的讉K性能。主要通过以下Ҏ实现: W一Q将大表按行或列分解q小? W二Q按不同的用L分解?Q?Q用尽可能低的隔离性别。隔L别是指ؓ保证数据库数据的完整性和一致性而多用户事务隔ȝE度QSQL92定义?U隔L别:未提交读、提交读、可重复d可串行。如果选择q高的隔L别,如可串行Q虽然系l可以因实现更好隔离性而更大程度上保证数据的完整性和一致性,但各事务间冲H而死锁的Z大大增加Q大大媄响了pȝ性能?Q?Q用绑定连? l定q接允许两个或多个事务连接共享事务和锁,而且M一个事务连接要甌锁如同另外一个事务要甌锁一P因此可以允许q些事务׃n数据而不会有加锁的冲H?nbsp;
可?/span> DECLARE GLOBAL TEMPORARY TABLE 语句来定义时表?/span>DB2的时表是基于会话的Q且在会话之间是隔离的。当会话l束Ӟ临时表的数据被删除,临时表被隐式怸。对临时表的定义不会?/span>SYSCAT.TABLES中出?/span>
下面是定义时表的一个示例:
DECLARE GLOBAL TEMPORARY TABLE gbl_temp
LIKE empltabl
ON COMMIT DELETE ROWS
NOT LOGGED
IN usr_tbsp
此语句创Z个名?/span> gbl_temp的用户时表。定义此用户临时?/span> 所使用的列的名U和说明?/span> empltabl的列的名U和说明完全相同。隐式定?/span> 只包括列名、数据类型、可为空Ҏ和列缺省值属性。未定义所有其他列属性,包括唯一U束、外部关键字U束、触发器和烦引。执?/span> COMMIT 操作Ӟ若未对该表打开 WITH HOLD 游标Q则该表中的所有数据都被删除。不记录对用户时表所作的更改。用户时表被放在指定的用户临时表空间中。此表空间必d在,否则此表的声明将p|?/span>
]]>ORACLE之常用FAQ V1.0 (4) W四部分、性能调整http://www.shnenglu.com/ivenher/articles/13153.html爱饭?/dc:creator>爱饭?/author>Fri, 29 Sep 2006 09:26:00 GMThttp://www.shnenglu.com/ivenher/articles/13153.htmlhttp://www.shnenglu.com/ivenher/comments/13153.htmlhttp://www.shnenglu.com/ivenher/articles/13153.html#Feedback0http://www.shnenglu.com/ivenher/comments/commentRss/13153.htmlhttp://www.shnenglu.com/ivenher/services/trackbacks/13153.htmlW四部分、性能调整
[Q]如果讄自动跟踪
[A]用systemd 执行$ORACLE_HOME/rdbms/admin/utlxplan.sql创徏计划?br />执行$ORACLE_HOME/sqlplus/admin/plustrce.sql创徏plustrace角色 如果惌划表让每个用户都能用,?br />SQL>create public synonym plan_table for plan_table; SQL> grant all on plan_table to public; 如果惌自动跟踪的角色让每个用户都能使用Q则 SQL> grant plustrace to public; 通过如下语句开?停止跟踪 SET AUTOTRACE ON |OFF | ON EXPLAIN | ON STATISTICS | TRACEONLY | TRACEONLY EXPLAIN [Q]如果跟踪自己的会话或者是别h的会?/font> [A]跟踪自己的会话很?br />Alter session set sql_trace true|false Or Exec dbms_session.set_sql_trace(TRUE); 如果跟踪别h的会话,需要调用一个包 exec dbms_system.set_sql_trace_in_session(sid,serial#,true|false) 跟踪的信息在user_dump_dest 目录下可以找到或通过如下脚本获得文g名称Q适用于Win环境Q如果是unix需要做一定修改) SELECT p1.value||'\'||p2.value||'_ora_'||p.spid||'.ora' filename FROM v$process p, v$session s, v$parameter p1, v$parameter p2 WHERE p1.name = 'user_dump_dest' AND p2.name = 'db_name' AND p.addr = s.paddr AND s.audsid = USERENV ('SESSIONID') 最后,可以通过Tkprof来解析跟t文Ӟ?br />Tkprof 原文?目标文g sys=n [Q]怎么讄整个数据库系l跟t?/font> [A]其实文档上的alter system set sql_trace=true是不成功?br />但是可以通过讄事g来完成这个工作,作用相等 alter system set events '10046 trace name context forever,level 1'; 如果关闭跟踪Q可以用如下语句 alter system set events '10046 trace name context off'; 其中的level 1与上面的8都是跟踪U别 level 1Q跟tSQL语句Q等于sql_trace=true level 4Q包括变量的详细信息 level 8Q包括等待事?br />level 12Q包括绑定变量与{待事g [Q]怎么h据OSq程快速获得DBq程信息与正在执行的语句 [A]有些时候,我们在OS上操作,象TOP之后我们得到的OSq程Q怎么快速根据OS信息获得DB信息呢? 我们可以~写如下脚本Q?br />$more whoit.sh #!/bin/sh sqlplus /nolog 100,cascade=> TRUE); dbms_stats.gather_table_stats(User,TableName,degree => 4,cascade => true); q是对命令与工具包的一些ȝ 1、对于分Q徏议用DBMS_STATSQ而不是用Analyze语句? a) 可以q行q行Q对多个用户Q多个Table b) 可以得到整个分区表的数据和单个分区的数据? c) 可以在不同别上Compute StatisticsQ单个分区,子分区,全表Q所有分? d) 可以倒出l计信息 e) 可以用户自动攉l计信息 2、DBMS_STATS的缺? a) 不能Validate Structure b) 不能攉CHAINED ROWS, 不能攉CLUSTER TABLE的信息,q两个仍旧需要用Analyze语句? c) DBMS_STATS 默认不对索引q行AnalyzeQ因为默认Cascade是FalseQ需要手工指定ؓTrue 3、对于oracle 9里面的External TableQAnalyze不能使用Q只能用DBMS_STATS来收集信息?br />[Q]怎么样快速重整烦?/font> [A]通过rebuild语句Q可以快速重整或Ud索引到别的表I间 rebuild有重建整个烦引数的功能,可以在不删除原始索引的情况下改变索引的存储参?br />语法?br />alter index index_name rebuild tablespace ts_name storage(…?; 如果要快速重建整个用户下的烦引,可以用如下脚本,当然Q需要根据你自己的情况做相应修改 SQL> set heading off SQL> set feedback off SQL> spool d:\index.sql SQL> SELECT 'alter index ' || index_name || ' rebuild ' ||'tablespace INDEXES storage(initial 256K next 256K pctincrease 0);' FROM all_indexes WHERE ( tablespace_name != 'INDEXES' OR next_extent != ( 256 * 1024 ) ) AND owner = USER SQL>spool off 另外一个合q烦引的语句?br />alter index index_name coalesceQ这个语句仅仅是合ƈ索引中同一U的leaf block 消耗不大,对于有些索引中存在大量空间浪费的情况下,有一些作用?br />[Q]如何使用Hint提示 [A] 在select/delete/update后写/*+ hint */ ?select /*+ index(TABLE_NAME INDEX_NAME) */ col1... 注意/*?之间不能有空?br />如用hint指定使用某个索引 select /*+ index(cbotab) */ col1 from cbotab; select /*+ index(cbotab cbotab1) */ col1 from cbotab; select /*+ index(a cbotab1) */ col1 from cbotab a; 其中 TABLE_NAME是必要写的Q且如果在查询中使用了表的别名,在hint也要用表的别名来代替表名; INDEX_NAME可以不必写,Oracle会根据统计值选一个烦? 如果索引名或表名写错了,那这个hint׃被忽? [Q]怎么样快速复制表或者是插入数据 [A]快速复制表可以指定Nologging选项 如:Create table t1 nologging as select * from t2; 快速插入数据可以指定append提示Q但是需要注?br />noarchivelog模式下,默认用了append是nologging模式的? 在archivelog下,需要把表设|程Nologging模式?br />如insert /*+ append */ into t1 select * from t2 注意Q如果在9i环境中ƈ讄了FORCE LOGGINGQ则以上操作是无效的Qƈ不会加快Q当Ӟ可以通过如下语句讄为NO FORCE LOGGING?br />Alter database no force logging; 是否开启了FORCE LOGGINGQ可以用如下语句查看 SQL> select force_logging from v$database; [Q]怎么避免使用特定索引 [A]在很多时候,Oracle会错误的使用索引而导致效率的明显下降Q我们可以用一点点技巧而避免用不该用的索引Q如Q?br />表test,有字Da,b,c,dQ在a,b,c上徏立联合烦引inx_a(a,b,c)Q在b上单独徏立了一个烦引Inx_b(b)?br />在正常情况下Qwhere a=? and b=? and c=?会用到烦引inx_aQ?br />where b=?会用到烦引inx_b 但是Qwhere a=? and b=? and c=? group by b会用到哪个烦引呢Q在分析数据不正(很长旉没有分析Q或Ҏ没有分析数据的情况下Qoracle往往会用烦引inx_b。通过执行计划的分析,q个索引的用,大大耗费查询旉?br />当然Q我们可以通过如下的技巧避免用inx_bQ而用inx_a?br />where a=? and b=? and c=? group by b||'' --如果b是字W?br />where a=? and b=? and c=? group by b+0 --如果b是数?br />通过q样单的改变Q往往可以是查询时间提交很多?br />当然Q我们也可以使用no_index提示Q相信很多h没有用过Q也是一个不错的ҎQ?br />select /*+ no_index(t,inx_b) */ * from test t where a=? and b=? and c=? group by b [Q]Oracle什么时候会使用跌式烦引扫?/font> [A]q是9i的一个新Ҏ蟩跃式索引扫描(Index Skip Scan). 例如表有索引index(a,b,c)Q当查询条g?br />where b=?的时候,可能会用到索引index(a,b,c) 如,执行计划中出现如下计划: INDEX (SKIP SCAN) OF 'TEST_IDX' (NON-UNIQUE) Oracle的优化器(q里指的是CBO)能对查询应用Index Skip Scans臛_要有几个条g: 1 优化器认为是合适的?br />2 索引中的前导列的唯一值的数量能满一定的条gQ如重复值很多)?br />3 优化器要知道前导列的值分?通过分析/l计表得??br />4 合适的SQL语句 {?br />[Q]怎么样创Z用虚拟烦?/font> [A]可以使用nosegment选项Q如 create index virtual_index_name on table_name(col_name) nosegment; 如果在哪个session需要测试虚拟烦引,可以利用隐含参数来处?br />alter session set "_use_nosegment_indexes" = true; 可以利用explain plan for select ……来看虚拟烦引的效果 利用@$ORACLE_HOME/rdbms/admin/utlxpls查看执行计划 最后,Ҏ需要,我们可以删除虚拟索引Q如普通烦引一?br />drop index virtual_index_name; 注意Q虚拟烦引ƈ不是物理存在的,所以虚拟烦引ƈ不等同于物理索引Q不要用自动跟踪L试虚拟烦引,因ؓ那是实际执行的效果,是用不到虚拟索引的?br />[Q]怎样监控无用的烦?/font> [A]Oracle 9i以上Q可以监控烦引的使用情况Q如果一D|间内没有使用的烦引,一般就是无用的索引 语法为: 开始监控:alter index index_name monitoring usage; 查用状态:select * from v$object_usage; 停止监控Qalter index index_name nomonitoring usage; 当然Q如果想监控整个用户下的索引Q可以采用如下的脚本Q?br />set heading off set echo off set feedback off set pages 10000 spool start_index_monitor.sql SELECT 'alter index '||owner||'.'||index_name||' monitoring usage;' FROM dba_indexes WHERE owner = USER; spool off set heading on set echo on set feedback on ------------------------------------------------ set heading off set echo off set feedback off set pages 10000 spool stop_index_monitor.sql SELECT 'alter index '||owner||'.'||index_name||' nomonitoring usage;' FROM dba_indexes WHERE owner = USER; spool off set heading on set echo on set feedback on [Q]怎么栯固定我的执行计划 [A]可以使用OUTLINE来固定SQL语句的执行计?br />用如下语句可以创Z个OUTLINE Create oe replace outline OutLn_Name on Select Col1,Col2 from Table where …?br />如果要删除OutlineQ可以采?br />Drop Outline OutLn_Name; 对于已经创徏了的OutLineQ存攑֜OUTLN用户的OL$HINTS表下?br />对于有些语句Q你可以使用update outln.ol$hints来更新outline 如update outln.ol$hints(ol_name,'TEST1','TEST2','TEST2','TEST1) where ol_name in ('TEST1','TEST2'); q样Q你把Test1 OUTLINE与Test2 OUTLINE互换?br />如果惛_用已l存在的OUTLINEQ需要设|以下参?br />Alter system/session set Query_rewrite_enabled = true Alter system/session set use_stored_outlines = true [Q]v$sysstat中的class分别代表什?/font> [A]l计cd 1 代表事例zd 2 代表Redo bufferzd 4 代表?br />8 代表数据~冲zd 16 代表OSzd 32 代表q行zd 64 代表表访?br />128 代表调试信息 [Q]怎么杀掉特定的数据库会?/font> [A] Alter system kill session 'sid,serial#'; 或?br />alter system disconnect session 'sid,serial#' immediate; 在win上,q可以采用oracle提供的orakill杀掉一个线E(其实是一个Oracleq程Q?br />在Linux/Unix上,可以直接利用kill杀掉数据库q程对应的OSq程 [Q]怎么快速查N与锁{待 [A]数据库的锁是比较耗费资源的,特别是发生锁{待的时候,我们必须扑ֈ发生{待的锁Q有可能的话Q杀掉该q程?br />q个语句查扑ֈ数据库中所有的DML语句产生的锁Q还可以发现QQ何DML语句其实产生了两个锁Q一个是表锁Q一个是行锁?br />可以通过alter system kill session ‘sid,serial#’来杀掉会?br />SELECT /*+ rule */ s.username, decode(l.type,'TM','TABLE LOCK', 'TX','ROW LOCK', NULL) LOCK_LEVEL, o.owner,o.object_name,o.object_type, s.sid,s.serial#,s.terminal,s.machine,s.program,s.osuser FROM v$session s,v$lock l,dba_objects o WHERE l.sid = s.sid AND l.id1 = o.object_id(+) AND s.username is NOT NULL 如果发生了锁{待Q我们可能更想知道是谁锁了表而引赯的等?br />以下的语句可以查询到谁锁了表Q而谁在等待?br />SELECT /*+ rule */ lpad(' ',decode(l.xidusn ,0,3,0))||l.oracle_username User_name, o.owner,o.object_name,o.object_type,s.sid,s.serial# FROM v$locked_object l,dba_objects o,v$session s WHERE l.object_id=o.object_id AND l.session_id=s.sid ORDER BY o.object_id,xidusn DESC 以上查询l果是一个树状结构,如果有子节点Q则表示有等待发生。如果想知道锁用了哪个回滚段Q还可以兌到V$rollnameQ其中xidusn是回滚D늚USN [Q] 如何有效的删除一个大?extent数很多的? [A] 一个有很多(100k)extent的表Q如果只是简单地用drop table的话Q会很大量消耗CPUQOracle要对fet$、uet$数据字典q行操作Q,可能会用上几天的旉Q较好的Ҏ是分多次删除extentQ以减轻q种消耗: 1. truncate table big-table reuse storage; 2. alter table big-table deallocate unused keep 2000m ( 原来大小的n-1/n); 3. alter table big-table deallocate unused keep 1500m ; .... 4. drop table big-table; [Q]如何收羃临时数据文g的大?/font> [A]9i以下版本采用 ALTER DATABASE DATAFILE 'file name' RESIZE 100McM的语?br />9i以上版本采用 ALTER DATABASE TEMPFILE 'file name' RESIZE 100M 注意Q时数据文件在使用Ӟ一般不能收~,除非关闭数据库或断开所有会话,停止对时数据文件的使用?br />[Q]怎么清理临时D?/font> [A]可以使用如下办法 1?使用如下语句查看一下认谁在用时段 SELECT username,sid,serial#,sql_address,machine,program, tablespace,segtype, contents FROM v$session se,v$sort_usage su WHERE se.saddr=su.session_addr 2?那些正在使用临时D늚q程 SQL>Alter system kill session 'sid,serial#'; 3、把TEMP表空间回~一?br />SQL>Alter tablespace TEMP coalesce; q可以用诊断事?br />1?定TEMP表空间的ts# SQL> select ts#, name FROM v$tablespace; TS# NAME ----------------------- 0 SYSYEM 1 RBS 2 USERS 3* TEMP …?br />2?执行清理操作 alter session set events 'immediate trace name DROP_SEGMENTS level TS#+1' 说明Q? temp表空间的TS# ?3*, So TS#+ 1= 4 如果x除所有表I间的时段Q则 TS# = 2147483647 [Q]怎么样dump数据库内部结构,如上面显C的控制文g的结?/font> [A]常见的有 1、分析数据文件块Q{储数据文件n的块m alter system dump datafile n block m 2、分析日志文?br />alter system dump logfile logfilename; 3、分析控制文件的内容 alter session set events 'immediate trace name CONTROLF level 10' 4、分析所有数据文件头 alter session set events 'immediate trace name FILE_HDRS level 10' 5、分析日志文件头 alter session set events 'immediate trace name REDOHDR level 10' 6、分析系l状态,最好每10分钟一ơ,做三ơ对?br />alter session set events 'immediate trace name SYSTEMSTATE level 10' 7、分析进E状?br />alter session set events 'immediate trace name PROCESSSTATE level 10' 8、分析Library Cache的详l情?br />alter session set events 'immediate trace name library_cache level 10' [Q]如何获得所有的事g代码 [A] 事g代码范围一般从10000 to 10999Q以下列Zq个范围的事件代码与信息 SET SERVEROUTPUT ON DECLARE err_msg VARCHAR2(120); BEGIN dbms_output.enable (1000000); FOR err_num IN 10000..10999 LOOP err_msg := SQLERRM (-err_num); IF err_msg NOT LIKE '%Message '||err_num||' not found%' THEN dbms_output.put_line (err_msg); END IF; END LOOP; END; / 在Unixpȝ上,事g信息攑֜一个文本文仉 $ORACLE_HOME/rdbms/mesg/oraus.msg 可以用如下脚本查看事件信? event=10000 while [ $event -ne 10999 ] do event=`expr $event + 1` oerr ora $event done 对于已经保?正在跟踪的事Ӟ可以用如下脚本获?br />SET SERVEROUTPUT ON DECLARE l_level NUMBER; BEGIN FOR l_event IN 10000..10999 LOOP dbms_system.read_ev (l_event,l_level); IF l_level > 0 THEN dbms_output.put_line ('Event '||TO_CHAR (l_event)|| ' is set at level '||TO_CHAR (l_level)); END IF; END LOOP; END; / [Q]什么是STATSPACKQ我怎么使用它? [A]Statspack是Oracle 8i以上提供的一个非常好的性能监控与诊断工P基本上全部包含了BSTAT/ESTAT的功能,更多的信?br />可以参考附带文?ORACLE_HOME/rdbms/admin/spdoc.txt? 安装Statspack: cd $ORACLE_HOME/rdbms/admin sqlplus "/ as sysdba" @spdrop.sql -- 卸蝲Q第一ơ可以不需?br />sqlplus "/ as sysdba" @spcreate.sql -- 需要根据提C入表I间?br />使用Statspack: sqlplus perfstat/perfstat exec statspack.snap; -- q行信息攉l计Q每ơ运行都生一个快照号 -- 获得快照P必须要有两个以上的快照,才能生成报表 select SNAP_ID, SNAP_TIME from STATS$SNAPSHOT; @spreport.sql -- 输入需要查看的开始快照号与结束快照号 其他相关脚本s: spauto.sql - 利用dbms_job提交一个作业,自动的进行STATPACK的信息收集统? sppurge.sql - 清除一D范围内的统计信息,需要提供开始快照与l束快照?br />sptrunc.sql - 清除(truncate)所有统计信?/span>
]]>ORACLE之常用FAQ V1.0 (2) W二部分、ORACLE构架体系http://www.shnenglu.com/ivenher/articles/13151.html爱饭?/dc:creator>爱饭?/author>Fri, 29 Sep 2006 09:24:00 GMThttp://www.shnenglu.com/ivenher/articles/13151.htmlhttp://www.shnenglu.com/ivenher/comments/13151.htmlhttp://www.shnenglu.com/ivenher/articles/13151.html#Feedback0http://www.shnenglu.com/ivenher/comments/commentRss/13151.htmlhttp://www.shnenglu.com/ivenher/services/trackbacks/13151.htmlW二部分、ORACLE构架体系
[Q]ORACLE的有那些数据cd
[A]常见的数据类型有 CHAR固定长度字符域,最大长度可?000个字? NCHAR多字节字W集的固定长度字W域Q长度随字符集而定Q最多ؓ2000个字W或2000个字? VARCHAR2可变长度字符域,最大长度可?000个字W? NVARCHAR2多字节字W集的可变长度字W域Q长度随字符集而定Q最多ؓ4000个字W或4000个字? DATE用于存储全部日期的固定长?7个字?字符域,旉作ؓ日期的一部分存储其中。除? 通过讄init.ora文g的NLS_DATE_FORMAT参数来取代日期格式,否则查询Ӟ日期? DD-MON-YY格式表示Q如13-APR-99表示1999.4.13 NUMBER可变长度数值列Q允许gؓ0、正数和负数。NUMBER值通常?个字节或更少的字节存储,最?1字节 LONG可变长度字符域,最大长度可?GB RAW表示二进制数据的可变长度字符域,最长ؓ2000个字? LONGRAW表示二进制数据的可变长度字符域,最长ؓ2GB MLSLABEL只用于TrustedOracleQ这个数据类型每行??个字? BLOB二进制大对象Q最大长度ؓ4GB CLOB字符大对象,最大长度ؓ4GB NCLOB多字节字W集的CLOB数据cdQ最大长度ؓ4GB BFILE外部二进制文Ӟ大小由操作系l决? ROWID表示RowID的二q制数据QOracle8RowID的数gؓ10个字节,在Oracle7中用的限定 RowID格式?个字? UROWID用于数据d的二q制数据Q最大长度ؓ4000个字? [Q]Oracle有哪些常见关键字Q不能被用于对象?/font> [A]?i版本ZQ一般保留关键字不能用做对象?br />ACCESS ADD ALL ALTER AND ANY AS ASC AUDIT BETWEEN BY CHAR CHECK CLUSTER COLUMN COMMENT COMPRESS CONNECT CREATE CURRENT DATE DECIMAL DEFAULT DELETE DESC DISTINCT DROP ELSE EXCLUSIVE EXISTS FILE FLOAT FOR FROM GRANT GROUP HAVING IDENTIFIED IMMEDIATE IN INCREMENT INDEX INITIAL INSERT INTEGER INTERSECT INTO IS LEVEL LIKE LOCK LONG MAXEXTENTS MINUS MLSLABEL MODE MODIFY NOAUDIT NOCOMPRESS NOT NOWAIT NULL NUMBER OF OFFLINE ON ONLINE OPTION OR ORDER PCTFREE PRIOR PRIVILEGES PUBLIC RAW RENAME RESOURCE REVOKE ROW ROWID ROWNUM ROWS SELECT SESSION SET SHARE SIZE SMALLINT START SUCCESSFUL SYNONYM SYSDATE TABLE THEN TO TRIGGER UID UNION UNIQUE UPDATE USER VALIDATE VALUES VARCHAR VARCHAR2 VIEW WHENEVER WHERE WITH 详细信息可以查看v$reserved_words视图 [Q]怎么查看数据库版?/font> [A]select * from v$version 包含版本信息Q核心版本信息,位数信息(32位或64?{?br />至于位数信息Q在linux/unixq_上,可以通过file查看Q如 file $ORACLE_HOME/bin/oracle [Q]怎么查看数据库参?/font> [A]show parameter 参数?br />如通过show parameter spfile可以查看9i是否使用spfile文g 或者select * from v$parameter 除了q部分参敎ͼOracleq有大量隐含参数Q可以通过如下语句查看: SELECT NAME ,VALUE ,decode(isdefault, 'TRUE','Y','N') as "Default" ,decode(ISEM,'TRUE','Y','N') as SesMod ,decode(ISYM,'IMMEDIATE', 'I', 'DEFERRED', 'D', 'FALSE', 'N') as SysMod ,decode(IMOD,'MODIFIED','U', 'SYS_MODIFIED','S','N') as Modified ,decode(IADJ,'TRUE','Y','N') as Adjusted ,description FROM ( --GV$SYSTEM_PARAMETER SELECT x.inst_id as instance ,x.indx+1 ,ksppinm as NAME ,ksppity ,ksppstvl as VALUE ,ksppstdf as isdefault ,decode(bitand(ksppiflg/256,1),1,'TRUE','FALSE') as ISEM ,decode(bitand(ksppiflg/65536,3), 1,'IMMEDIATE',2,'DEFERRED','FALSE') as ISYM ,decode(bitand(ksppstvf,7),1,'MODIFIED','FALSE') as IMOD ,decode(bitand(ksppstvf,2),2,'TRUE','FALSE') as IADJ ,ksppdesc as DESCRIPTION FROM x$ksppi x ,x$ksppsv y WHERE x.indx = y.indx AND substr(ksppinm,1,1) = '_' AND x.inst_id = USERENV('Instance') ) ORDER BY NAME [Q]怎么h看数据库字符?/font> [A]数据库服务器字符集select * from nls_database_parametersQ其来源于props$Q是表示数据库的字符集?br />客户端字W集环境select * from nls_instance_parameters,其来源于v$parameterQ?br />表示客户端的字符集的讄Q可能是参数文gQ环境变量或者是注册?br />会话字符集环?select * from nls_session_parametersQ其来源于v$nls_parametersQ表CZ话自q讄Q可能是会话的环境变量或者是alter session完成Q如果会话没有特D的讄Q将与nls_instance_parameters一致?br />客户端的字符集要求与服务器一_才能正确昄数据库的非Ascii字符。如果多个设|存在的时候,alter session>环境变量>注册?gt;参数文g 字符集要求一_但是语言讄却可以不同,语言讄用英文。如字符集是zhs16gbkQ则nls_lang可以是American_America.zhs16gbk?br />[Q]怎么样修改字W集 [A]8i以上版本可以通过alter database来修改字W集Q但也只限于子集到超集,不徏议修改props$表,可能导致严重错误?br />Startup nomount; Alter database mount exclusive; Alter system enable restricted session; Alter system set job_queue_process=0; Alter database open; Alter database character set zhs16gbk; [Q]怎样建立Z函数索引 [A]8i以上版本Q确?br />Query_rewrite_enabled=true Query_rewrite_integrity=trusted Compatible=8.1.0以上 Create index indexname on table (function(field)); [Q]怎么L动表或表分区 [A]Ud表的语法 Alter table tablename move [Tablespace new_name Storage(initial 50M next 50M pctincrease 0 pctfree 10 pctused 50 initrans 2) nologging] Ud分区的语?br />alter table tablename move (partition partname) [update global indexes] 之后之后必须重徏索引 Alter index indexname rebuild 如果表有LobD,那么正常的Alter不能UdLobD到别的表空_而仅仅是Ud了表D,可以采用如下的方法移动LobD?br />alter table tablename move lob(lobsegname) store as (tablespace newts); [Q]怎么获得当前的SCN [A]9i以下版本 select max(ktuxescnw*power(2,32)+ktuxescnb) from x$ktuxe; 如果?i以上版本Q还可以通过以下语句获取 select dbms_flashback.get_system_change_number from dual; [Q]ROWID的结构与l成 [A]8以上版本的ROWIDl成 OOOOOOFFFBBBBBBRRR 8以下ROWIDl成Q也叫受限RowidQ?br />BBBBBBBB.RRRR.FFFF 其中QO是对象IDQF是文件IDQB是块IDQR是行ID 如果我们查询一个表的ROWIDQ根据其中块的信息,可以知道该表切占用了多个块,q而知道占用了多少数据I间Q此数据I间不等于表的分配空_ [Q]怎么栯取对象的DDL语句 [A]W三方工具就不说了主要说一?i以上版本的dbms_metadata 1、获得单个对象的DDL语句 set heading off set echo off set feedback off set pages off set long 90000 select dbms_metadata.get_ddl('TABLE','TABLENAME','SCAME') from dual; 如果获取整个用户的脚本,可以用如下语?br />select dbms_metadata.get_ddl('TABLE',u.table_name) from user_tables u; 当然Q如果是索引Q则需要修改相关table到index [Q]如何创徏U束的烦引在别的表空间上 [A]1、先创徏索引Q再创徏U束 2、利用如下语句创?br />create table test (c1 number constraint pk_c1_id primary key using index tablespace useridex, c2 varchar2(10) ) tablespace userdate; [Q]怎么知道那些表没有徏立主?/font> [A]一般的情况下,表的主键是必要的Q没有主键的表可以说是不W合设计规范的?br />SELECT table_name FROM User_tables t WHERE NOT EXISTS (SELECT table_name FROM User_constraints c WHERE constraint_type = 'P' AND t.table_name=c.table_name) 其它相关数据字典解释 user_tables ?br />user_tab_columns 表的?br />user_constraints U束 user_cons_columns U束与列的关p?br />user_indexes 索引 user_ind_columns 索引与列的关p?br />[Q]dbms_output提示~冲Z够,怎么增加 [A]dbms_output.enable(20000); 另外Q如果dbms_output的信息不能显C, 需要设|?br />set serveroutput on [Q]怎么样修改表的列?/font> [A]9i以上版本可以采用rname命o ALTER TABLE UserName.TabName RENAME COLUMN SourceColumn TO DestColumn 9i以下版本可以采用create table …?as select * from SourceTable的方式?br />另外Q?i以上可以支持删除列了 ALTER TABLE UserName.TabName SET UNUSED (ColumnName) CASCADE CONSTRAINTS ALTER TABLE UserName.TabName DROP (ColumnName) CASCADE CONSTRAINTS [Q]怎么Lsqlplus安装帮助 [A]SQLPLUS的帮助必L工安装,shell脚本?ORACLE_HOME/bin/helpins 在安装之前,必须先设|SYSTEM_PASS环境变量Q如Q?br />$ setenv SYSTEM_PASS SYSTEM/MANAGER $ helpins 如果不设|该环境变量Q将在运行脚本的时候提C入环境变?br />当然Q除了shell脚本Q还可以利用sql脚本安装Q那׃用设|环境变量了Q但是,我们必须以systemd?br />$ sqlplus system/manager SQL> @?/sqlplus/admin/help/helpbld.sql helpus.sql 安装之后Q你可以象如下的方法用帮助了 SQL> help index [Q]怎么样快速下载Oracle补丁 [A]我们先获得下载服务器地址Q在http面上有 ftp://updates.oracle.com 然后用ftpdQ用户名与密码是metalink的用户名与密?br />如我们知道了补丁?095277 (9204的补丁集)Q则 ftp> cd 3095277 250 Changed directory OK. ftp> ls 200 PORT command OK. 150 Opening data connection for file listing. p3095277_9204_AIX64-5L.zip p3095277_9204_AIX64.zip …?br />p3095277_9204_WINNT.zip 226 Listing complete. Data connection has been closed. ftp: 208 bytes received in 0.02Seconds 13.00Kbytes/sec. ftp> 知道了这个信息,我们用用flashgetQ网l蚂蚁就可以下蝲了? d如下q接 ftp://updates.oracle.com/3095277/p3...04_AIX64-5L.zip 或替换后面的部分为所需要的内容 注意Q如果是flashgetQ网l蚂蚁请输入认证用户名及密码Q就是你的metalink的用户名与密码! [Q]如何Ud数据文g [A]1、关闭数据库Q利用os拯 a.shutdown immediate关闭数据?br />b.在os下拷贝数据文件到新的地点 c.Startup mount 启动到mount?br />d.Alter database rename datafile '老文? to '新文?; e.Alter database open; 打开数据?br />2、利用Rman联机操作 RMAN> sql "alter database datafile ''file name'' offline"; RMAN> run { 2> copy datafile 'old file location' 3> to 'new file location'; 4> switch datafile ' old file location' 5> to datafilecopy ' new file location'; 6> } RMAN> sql "alter database datafile ''file name'' online"; 说明Q利用OS拯也可以联机操作,不关闭数据库Q与rman的步骤一P利用rman与利用os拯的原理一P在rman中copy是拷贝数据文Ӟ相当于OS的cpQ而switch则相当于alter database renameQ用来更新控制文件?br />[Q]如果理联机日志l与成员 [A]以下是常见操作,如果在OPA/RAC下注意线E号 增加一个日志文件组 Alter database add logfile [group n] '文g全名' size 10M; 在这个组上增加一个成?br />Alter database add logfile member '文g全名' to group n; 在这个组上删除一个日志成?br />Alter database drop logfile member '文g全名'; 删除整个日志l?br />Alter database drop logfile group n; [Q]怎么栯REDO BLOCK的大?/font> [A]计算Ҏ?redo size + redo wastage) / redo blocks written + 16 具体见如下例?br />SQL> select name ,value from v$sysstat where name like '%redo%'; NAME VALUE ---------------------------------------------------------------- ---------- redo synch writes 2 redo synch time 0 redo entries 76 redo size 19412 redo buffer allocation retries 0 redo wastage 5884 redo writer latching time 0 redo writes 22 redo blocks written 51 redo write time 0 redo log space requests 0 redo log space wait time 0 redo log switch interrupts 0 redo ordering marks 0 SQL> select (19412+5884)/51 + 16 '"Redo black(byte)" from dual; Redo black(byte) ------------------ 512 [Q]控制文g包含哪些基本内容 [A]控制文g主要包含如下条目Q可以通过dump控制文g内容看到 DATABASE ENTRY CHECKPOINT PROGRESS RECORDS REDO THREAD RECORDS LOG FILE RECORDS DATA FILE RECORDS TEMP FILE RECORDS TABLESPACE RECORDS LOG FILE HISTORY RECORDS OFFLINE RANGE RECORDS ARCHIVED LOG RECORDS BACKUP SET RECORDS BACKUP PIECE RECORDS BACKUP DATAFILE RECORDS BACKUP LOG RECORDS DATAFILE COPY RECORDS BACKUP DATAFILE CORRUPTION RECORDS DATAFILE COPY CORRUPTION RECORDS DELETION RECORDS PROXY COPY RECORDS INCARNATION RECORDS [Q]如果发现表中有坏块,如何索其它未坏的数据 [A]首先需要找到坏块的IDQ可以运行dbverify实现Q,假设为,假定文g~码为。运行下面的查询查找D名Q? SELECT segment_name,segment_type,extent_id,block_id, blocks from dba_extents t where file_id = AND between block_id and (block_id + blocks - 1) 一旦找到坏D名Uͼ若段是一个表Q则最好徏立一个时表Q存攑֥的数据。若D|索引Q则删除它,再重建?br />create table good_table as select from bad_table where rowid not in (select rowid from bad_table where substr(rowid,10,6) = ) 在这里要注意8以前的受限ROWID与现在ROWID的差别?br />q可以用诊断事?0231 SQL> ALTER SYSTEM SET EVENTS '10231 trace name context forever,level 10'; 创徏一个时表good_table的表中除坏块的数据都索出?br />SQL>CREATE TABLE good_table as select * from bad_table; 最后关闭诊断事?br />SQL> ALTER SYSTEM SET EVENTS '10231 trace name context off '; 关于ROWID的结构,q可以参考dbms_rowid.rowid_create函数?br />[Q]我创Z数据库的所有用P我可以删除这些用户吗 [A]ORACLE数据库创建的时候,创徏了一pd默认的用户和表空_以下是他们的列表 ·SYS/CHANGE_ON_INSTALL or INTERNAL pȝ用户Q数据字典所有者,权限所有?SYSDBA) 创徏脚本Q?/rdbms/admin/sql.bsq and various cat*.sql 创徏后立即修改密?br />此用户不能被删除 ·SYSTEM/MANAGER 数据库默认管理用P拥有DBA角色权限 创徏脚本Q?/rdbms/admin/sql.bsq 创徏后立即修改密?br />此用户不能被删除 ·OUTLN/OUTLN 优化计划的存储大U用?br />创徏脚本Q?/rdbms/admin/sql.bsq 创徏后立即修改密?br />此用户不能被删除 --------------------------------------------------- ·SCOTT/TIGER, ADAMS/WOOD, JONES/STEEL, CLARK/CLOTH and BLAKE/PAPER. 实验、测试用P含有例表EMP与DEPT 创徏脚本Q?/rdbms/admin/utlsampl.sql 可以修改密码 用户可以被删除,在品环境徏议删除或锁定 ·HR/HR (Human Resources), OE/OE (Order Entry), SH/SH (Sales History). 实验、测试用P含有例表EMPLOYEES与DEPARTMENTS 创徏脚本Q?/demo/schema/mksample.sql 可以修改密码 用户可以被删除,在品环境徏议删除或锁定 ·DBSNMP/DBSNMP Oracle Intelligent agent 创徏脚本Q?/rdbms/admin/catsnmp.sql, called from catalog.sql 可以改变密码--需要放|新密码到snmp_rw.ora文g 如果不需要Intelligent AgentsQ可以删?br />--------------------------------------------------- 以下用户都是可选安装用?如果不需要,׃需要安?br />·CTXSYS/CTXSYS Oracle interMedia (ConText Cartridge)理用户 创徏脚本Q?/ctx/admin/dr0csys.sql ·TRACESVR/TRACE Oracle Trace server 创徏脚本Q?/rdbms/admin/otrcsvr.sql ·ORDPLUGINS/ORDPLUGINS Object Relational Data (ORD) User used by Time Series, etc. 创徏脚本Q?/ord/admin/ordinst.sql ·ORDSYS/ORDSYS Object Relational Data (ORD) User used by Time Series, etc 创徏脚本Q?/ord/admin/ordinst.sql ·DSSYS/DSSYS Oracle Dynamic Services and Syndication Server 创徏脚本Q?/ds/sql/dssys_init.sql ·MDSYS/MDSYS Oracle Spatial administrator user 创徏脚本Q?/ord/admin/ordinst.sql ·AURORA$ORB$UNAUTHENTICATED/INVALID Used for users who do not authenticate in Aurora/ORB 创徏脚本Q?/javavm/install/init_orb.sql called from ?/javavm/install/initjvm.sql ·PERFSTAT/PERFSTAT Oracle Statistics Package (STATSPACK) that supersedes UTLBSTAT/UTLESTAT 创徏脚本Q?/rdbms/admin/statscre.sql
[Q]怎么h询特D字W,如通配W?与_
[A]select * from table where name like 'A\_%' escape '\' [Q]如何插入单引号到数据库表?/font> [A]可以用ASCII码处理,其它Ҏ字符?amp;也一P? insert into t values('i'||chr(39)||'m'); -- chr(39)代表字符' 或者用两个单引可CZ?br />or insert into t values('I''m'); -- 两个''可以表示一? [Q]怎样讄事务一致?/font> [A]set transaction [isolation level] read committed; 默认语句U一致?br />set transaction [isolation level] serializable; read only; 事务U一致?br />[Q]怎么样利用游标更新数?/font> [A]cursor c1 is select * from tablename where name is null for update [of column] …?br />update tablename set column = …?br />where current of c1; [Q]怎样自定义异?/font> [A] pragma_exception_init(exception_name,error_number); 如果立即抛出异常 raise_application_error(error_number,error_msg,true|false); 其中number?20000?20999Q错误信息最?048B 异常变量 SQLCODE 错误代码 SQLERRM 错误信息 [Q]十进制与十六q制的{?/font> [A]8i以上版本Q?br />to_char(100,'XX') to_number('4D','XX') 8i以下的进制之间的转换参考如下脚?br />create or replace function to_base( p_dec in number, p_base in number ) return varchar2 is l_str varchar2(255) default NULL; l_num number default p_dec; l_hex varchar2(16) default '0123456789ABCDEF'; begin if ( p_dec is null or p_base is null ) then return null; end if; if ( trunc(p_dec) p_dec OR p_dec 20; [Q]怎么h取重复记?/font> [A]select * from table t1 where where t1.rowed != (select max(rowed) from table t2 where t1.id=t2.id and t1.name=t2.name) 或?br />select count(*), t.col_a,t.col_b from table t group by col_a,col_b having count(*)>1 如果惛_除重复记录,可以把第一个语句的select替换为delete [Q]怎么栯|自M?/font> [A]8i以上版本Q不影响M?br />pragma autonomous_transaction; …?br />commit|rollback; [Q]怎么样在q程中暂停指定时?/font> [A]DBMS_LOCK包的sleepq程 如:dbms_lock.sleep(5);表示暂停5U?br />[Q]怎么样快速计事务的旉与日志量 [A]可以采用cM如下的脚?br />DECLARE start_time NUMBER; end_time NUMBER; start_redo_size NUMBER; end_redo_size NUMBER; BEGIN start_time := dbms_utility.get_time; SELECT VALUE INTO start_redo_size FROM v$mystat m,v$statname s WHERE m.STATISTIC#=s.STATISTIC# AND s.NAME='redo size'; --transaction start INSERT INTO t1 SELECT * FROM All_Objects; --other dml statement COMMIT; end_time := dbms_utility.get_time; SELECT VALUE INTO end_redo_size FROM v$mystat m,v$statname s WHERE m.STATISTIC#=s.STATISTIC# AND s.NAME='redo size'; dbms_output.put_line('Escape Time:'||to_char(end_time-start_time)||' centiseconds'); dbms_output.put_line('Redo Size:'||to_char(end_redo_size-start_redo_size)||' bytes'); END; [Q]怎样创徏临时?/font> [A]8i以上版本 create global temporary tablename(column list) on commit preserve rows; --提交保留数据 会话临时?br />on commit delete rows; --提交删除数据 事务临时?br />临时表是相对于会话的Q别的会话看不到该会话的数据?br />[Q]怎么样在PL/SQL中执行DDL语句 [A]1?i以下版本dbms_sql?br />2?i以上版本q可以用 execute immediate sql; dbms_utility.exec_ddl_statement('sql'); [Q]怎么栯取IP地址 [A]服务?817以上)Qutl_inaddr.get_host_address 客户端:sys_context('userenv','ip_address') [Q]怎么样加密存储过E?/font> [A]用wrap命oQ如Q假定你的存储过E保存ؓa.sqlQ?br />wrap iname=a.sql PL/SQL Wrapper: Release 8.1.7.0.0 - Production on Tue Nov 27 22:26:48 2001 Copyright (c) Oracle Corporation 1993, 2000. All Rights Reserved. Processing a.sql to a.plb 提示a.sql转换为a.plbQ这是加密了的脚本Q执行a.plb卛_生成加密了的存储q程 [Q]怎么样在ORACLE中定时运行存储过E?/font> [A]可以利用dbms_job包来定时q行作业Q如执行存储q程Q一个简单的例子Q提交一个作业: VARIABLE jobno number; BEGIN DBMS_JOB.SUBMIT(:jobno, 'ur_procedure;',SYSDATE,'SYSDATE + 1'); commit; END; 之后Q就可以用以下语句查询已l提交的作业 select * from user_jobs; [Q]怎么样从数据库中获得毫秒 [A]9i以上版本Q有一个timestampcd获得毫秒Q如 SQL>select to_char(systimestamp,'yyyy-mm-dd hh24:mi:ssxff') time1, to_char(current_timestamp) time2 from dual; TIME1 TIME2 ----------------------------- ---------------------------------------------------------------- 2003-10-24 10:48:45.656000 24-OCT-03 10.48.45.656000 AM +08:00 可以看到Q毫U在to_char中对应的是FF?br />8i以上版本可以创徏一个如下的java函数 SQL>create or replace and compile java source named "MyTimestamp" as import java.lang.String; import java.sql.Timestamp; public class MyTimestamp { public static String getTimestamp() { return(new Timestamp(System.currentTimeMillis())).toString(); } }; SQL>java created. 注:注意java的语法,注意大小?br />SQL>create or replace function my_timestamp return varchar2 as language java name 'MyTimestamp.getTimestamp() return java.lang.String'; / SQL>function created. SQL>select my_timestamp,to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') ORACLE_TIME from dual; MY_TIMESTAMP ORACLE_TIME ------------------------ ------------------- 2003-03-17 19:15:59.688 2003-03-17 19:15:59 如果只想获得1/100U?hsecs)Q还可以利用dbms_utility.get_time [Q]如果存在更斎ͼ不存在就插入可以用一个语句实现吗 [A]9i已经支持了,是MergeQ但是只支持select子查询, 如果是单条数据记录,可以写作select …?from dual的子查询?br />语法为: MERGE INTO table USING data_source ON (condition) WHEN MATCHED THEN update_clause WHEN NOT MATCHED THEN insert_clause; ?br />MERGE INTO course c USING (SELECT course_name, period, course_hours FROM course_updates) cu ON (c.course_name = cu.course_name AND c.period = cu.period) WHEN MATCHED THEN UPDATE SET c.course_hours = cu.course_hours WHEN NOT MATCHED THEN INSERT (c.course_name, c.period, c.course_hours) VALUES (cu.course_name, cu.period, cu.course_hours); [Q]怎么实现左联Q右联与外联 [A]?i以前可以q么? 左联Q?br />select a.id,a.name,b.address from a,b where a.id=b.id(+) 双: select a.id,a.name,b.address from a,b where a.id(+)=b.id 外联 SELECT a.id,a.name,b.address FROM a,b WHERE a.id = b.id(+) UNION SELECT b.id,'' name,b.address FROM b WHERE NOT EXISTS ( SELECT * FROM a WHERE a.id = b.id); ?i以上Q已l开始支持SQL99标准Q所以,以上语句可以写成Q?br />默认内部联结Q?br />select a.id,a.name,b.address,c.subject from (a inner join b on a.id=b.id) inner join c on b.name = c.name where other_clause 左联 select a.id,a.name,b.address from a left outer join b on a.id=b.id where other_clause 双 select a.id,a.name,b.address from a right outer join b on a.id=b.id where other_clause 外联 select a.id,a.name,b.address from a full outer join b on a.id=b.id where other_clause or select a.id,a.name,b.address from a full outer join b using (id) where other_clause [Q]怎么实现一条记录根据条件多表插?/font> [A]9i以上可以通过Insert all语句完成Q仅仅是一个语句,如: INSERT ALL WHEN (id=1) THEN INTO table_1 (id, name) values(id,name) WHEN (id=2) THEN INTO table_2 (id, name) values(id,name) ELSE INTO table_other (id, name) values(id, name) SELECT id,name FROM a; 如果没有条g的话Q则完成每个表的插入Q如 INSERT ALL INTO table_1 (id, name) values(id,name) INTO table_2 (id, name) values(id,name) INTO table_other (id, name) values(id, name) SELECT id,name FROM a; [Q]如何实现行列转换 [A]1、固定列数的行列转换 ?br />student subject grade --------------------------- student1 语文 80 student1 数学 70 student1 p 60 student2 语文 90 student2 数学 80 student2 p 100 …?br />转换? 语文 数学 p student1 80 70 60 student2 90 80 100 …?br />语句如下Q?br />select student,sum(decode(subject,'语文', grade,null)) "语文", sum(decode(subject,'数学', grade,null)) "数学", sum(decode(subject,'p', grade,null)) "p" from table group by student 2、不定列行列转换 ?br />c1 c2 -------------- 1 ?br />1 ?br />1 ?br />2 ?br />2 ?br />3 ?br />…?br />转换?br />1 我是?br />2 知道 3 ?br />q一cd的{换必d助于PL/SQL来完成,q里l一个例?br />CREATE OR REPLACE FUNCTION get_c2(tmp_c1 NUMBER) RETURN VARCHAR2 IS Col_c2 VARCHAR2(4000); BEGIN FOR cur IN (SELECT c2 FROM t WHERE c1=tmp_c1) LOOP Col_c2 := Col_c2||cur.c2; END LOOP; Col_c2 := rtrim(Col_c2,1); RETURN Col_c2; END; / SQL> select distinct c1 ,get_c2(c1) cc2 from table;卛_ [Q]怎么样实现分l取前N条记?/font> [A]8i以上版本Q利用分析函?br />如获取每个部门薪水前三名的员工或每个班成l前三名的学生?br />Select * from (select depno,ename,sal,row_number() over (partition by depno order by sal desc) rn from emp) where rn host lsntctl start 或者unix/linuxq_?br />SQL>! windowsq_?br />SQL>$ ȝQHOST 可以直接执行OS命o? 备注Qcd命o无法正确执行?br />[Q]怎么讄存储q程的调用者权?/font> [A]普通存储过E都是所有者权限,如果惌|调用者权限,请参考如下语?br />create or replace procedure …?) AUTHID CURRENT_USER As begin …?br />end; [Q]怎么快速获得用户下每个表或表分区的记录?/font> [A]可以分析该用P然后查询user_tables字典Q或者采用如下脚本即?br />SET SERVEROUTPUT ON SIZE 20000 DECLARE miCount INTEGER; BEGIN FOR c_tab IN (SELECT table_name FROM user_tables) LOOP EXECUTE IMMEDIATE 'select count(*) from "' || c_tab.table_name || '"' into miCount; dbms_output.put_line(rpad(c_tab.table_name,30,'.') || lpad(miCount,10,'.')); --if it is partition table SELECT COUNT(*) INTO miCount FROM User_Part_Tables WHERE table_name = c_tab.table_name; IF miCount >0 THEN FOR c_part IN (SELECT partition_name FROM user_tab_partitions WHERE table_name = c_tab.table_name) LOOP EXECUTE IMMEDIATE 'select count(*) from ' || c_tab.table_name || ' partition (' || c_part.partition_name || ')' INTO miCount; dbms_output.put_line(' '||rpad(c_part.partition_name,30,'.') || lpad(miCount, 10,'.')); END LOOP; END IF; END LOOP; END; [A]怎么在Oracle中发邮g [Q]可以利用utl_smtp包发邮gQ以下是一个发送简单邮件的例子E序 /**************************************************************************** parameter: Rcpter in varchar2 接收者邮?br />Mail_Content in Varchar2 邮g内容 desc: ·发送邮件到指定邮箱 ·只能指定一个邮,如果需要发送到多个邮箱Q需要另外的辅助E序 ****************************************************************************/ CREATE OR REPLACE PROCEDURE sp_send_mail( rcpter IN VARCHAR2, mail_content IN VARCHAR2) IS conn utl_smtp.connection; --write title PROCEDURE send_header(NAME IN VARCHAR2, HEADER IN VARCHAR2) AS BEGIN utl_smtp.write_data(conn, NAME||': '|| HEADER||utl_tcp.CRLF); END; BEGIN --opne connect conn := utl_smtp.open_connection('smtp.com'); utl_smtp.helo(conn, 'oracle'); utl_smtp.mail(conn, 'oracle info'); utl_smtp.rcpt(conn, Rcpter); utl_smtp.open_data(conn); --write title send_header('From', 'Oracle Database'); send_header('To', '"Recipient" '); send_header('Subject', 'DB Info'); --write mail content utl_smtp.write_data(conn, utl_tcp.crlf || mail_content); --close connect utl_smtp.close_data(conn); utl_smtp.quit(conn); EXCEPTION WHEN utl_smtp.transient_error OR utl_smtp.permanent_error THEN BEGIN utl_smtp.quit(conn); EXCEPTION WHEN OTHERS THEN NULL; END; WHEN OTHERS THEN NULL; END sp_send_mail; [A]怎么样在Oracle中写操作pȝ文gQ如写日?/font> [Q]可以利用utl_file包,但是Q在此之前,要注意设|好Utl_file_dir初始化参?br />/************************************************************************** parameter:textContext in varchar2 日志内容 desc: ·写日?把内容记到服务器指定目录?br />·必须配置Utl_file_dir初始化参敎ͼq保证日志\径与Utl_file_dir路径一致或者是其中一?br />****************************************************************************/ CREATE OR REPLACE PROCEDURE sp_Write_log(text_context VARCHAR2) IS file_handle utl_file.file_type; Write_content VARCHAR2(1024); Write_file_name VARCHAR2(50); BEGIN --open file write_file_name := 'db_alert.log'; file_handle := utl_file.fopen('/u01/logs',write_file_name,'a'); write_content := to_char(SYSDATE,'yyyy-mm-dd hh24:mi:ss')||'||'||text_context; --write file IF utl_file.is_open(file_handle) THEN utl_file.put_line(file_handle,write_content); END IF; --close file utl_file.fclose(file_handle); EXCEPTION WHEN OTHERS THEN BEGIN IF utl_file.is_open(file_handle) THEN utl_file.fclose(file_handle); END IF; EXCEPTION WHEN OTHERS THEN NULL; END; END sp_Write_log;
]]>ORACLE中用动态游标的例子 http://www.shnenglu.com/ivenher/articles/13146.html爱饭?/dc:creator>爱饭?/author>Fri, 29 Sep 2006 07:54:00 GMThttp://www.shnenglu.com/ivenher/articles/13146.htmlhttp://www.shnenglu.com/ivenher/comments/13146.htmlhttp://www.shnenglu.com/ivenher/articles/13146.html#Feedback0http://www.shnenglu.com/ivenher/comments/commentRss/13146.htmlhttp://www.shnenglu.com/ivenher/services/trackbacks/13146.html /* * NAMEQ?br /> * get_ope_popedom * * PARAMETERQ?br /> * sta_id - 车站~号Q多个站时以逗号分隔 * * RETURN: * --对应车站~号的R站名Uͼ多个站时以逗号分隔 * * AUTHOR: * 舉| * * DESCRIPTION: * --Ҏ传入的R站编可回相应的车站名称 * */ as Result varchar2(1000); name_temp varchar2(40); type cursor_t is ref cursor; emp_cur cursor_t ; begin OPEN emp_cur FOR 'SELECT sta_name FROM station_code where sta_code =:1' using sta_id; LOOP FETCH emp_cur INTO name_temp; If (emp_cur%NOTFOUND) Then EXIT; End if; Result := Result || name_temp || ','; end loop; close emp_cur; Result := substr(Result,1,(length(Result)-1)); return(Result); end get_ope_popedom;
declare v_comm_percent constant number:=10; begin update emp set comm=sal*v_comm_percent where deptno=10; end SQL> / PL/SQL procedure successfully completed.
SQL>
命名的程序与匿名E序的执行不同,执行命名的程序块必须使用execute关键字:
create or replace procedure update_commission (v_dept in number,v_pervent in number default 10) is begin update emp set comm=sal*v_percent where deptno=v_dept; end
SQL>/
Procedure created
SQL>execute update_commission(10,15);
PL/SQL procedure successfully completed.
SQL>
如果在另一个命名程序块或匿名程序块中执行这个程序,那么׃需要EXECUTE兌字?br />
declare v_dept number; begin select a.deptno into v_dept from emp a where job='PRESIDENT' update_commission(v_dept); end SQL>/ PL/SQL procedure successfully completed SQL>
FUNCTION name [{parameter[,parameter,...])] RETURN datatypes IS [local declarations] BEGIN execute statements [EXCEPTION exception handlers] END [name]