详析Oracle数据库中锁、序列、索引管理

详析Oracle数据库中锁、序列、索引管理

1.1什么是锁

数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。而锁就是用于控制事务对数据的访问,实现事务的并发控制,保持数据库的一致性。

1.2锁的类型

DDL锁:被Oracle自动的发布和释放

DML锁:在事务处理的开始时被施加,而且在事务处理完成时被释放(使用Commit或Rollback时被释放)

内部锁:由Oracle自己管理以保护内部数据库结构

注:DDL锁由数据库自动管理;DML锁和内部锁可以由用户直接或间接管理。

1.3锁的粒度

1)TX锁:行级锁(事务锁),会阻止这行上其它DML操作,直到Commit或Rollback时被释放,它只有X排他锁

2)TM锁:表级锁。

2.1)Row-S 行共享(RS):共享行锁,即可被其他事务查询该行。

2.2)Row-X 行专用(RX):用于行的修改,即禁止其他事务对该行的所有操作。

2.3)Share 共享锁(S):阻止其他DML操作

2.4)S/Row-X 共享行专用(SRX):阻止其他事务操作

2.5)exclusive 专用(X):独立访问使用

3)数据库级锁:锁定数据库为限制模式alter system enable restricted session;以下语句将锁定数据库为只读模式

    startup mount; alter database open read only;

1.4锁的模式和使用

1)共享锁(Share Table Lock,S):

使用情况:当执行事务时,事务所要操作的表不希望被别的事务更新时可以使用。即某表被加锁后只能被加锁的事务全权控制,其他事务只能对该表执行查询操作。

加锁语法:Lock Table TableName In Share Mode;

使用度:中。当对表执行大面积更新操作时可使用,反之,则不用。

2)排它锁(Exclusive Table Lock,X):

使用情况:当执行事务时,事务所要操作的表不希望被别的事务执行任何操作时使用。即某表被加排它锁后只能被加锁事务全权控制,其他事务不能对该表执行任何操作。

加锁语法:Lock Table TableName In Exclusive Mode;

使用度:低。一般不使用。

3) 行级锁(Row Share Table Lock,RS):

使用情况:在一行或多行上不希望其他事务对所要操作的表的行执行更新操作时可以使用。即只对特定的行进行加锁,其他的行可以被其他事务进行所有操作。

加锁语法:LOCK TABLE TableName IN ROW SHARE MODE;

使用度:高。一般事务都使用它。

4) 行级排它锁(Row Exclusive Table Lock,RX):

使用情况:使用情况与3类似,但行级锁锁定的行可以被其他事务查询,而行级排他锁则不能执行任何操作。

加锁语法:LOCK TABLE TableName IN ROW EXCLUSIVE MODE;

使用度:高。

5)共享行级排它锁(Share Row Exclusive Table Lock,SRX):

使用情况:比共享锁有更多的限制,允许其他事务执行查询操作,但不允许执行查询更新(Select … From TableName For update…)

共享行级排它锁的语法为:Lock Table TableName In Share Row Exclusive Mode;

使用度:中。

当Oracle数据库发生TX锁等待时,如果不及时处理常常会引起Oracle数据库挂起,或导致死锁的发生,产生ORA-60的错误。

TX锁等待的分析

Oracle数据库中一般使用行级锁。

当Oracle检测到死锁产生时,中断并回滚死锁相关语句的执行,报ORA-00060的错误并记录在数据库的日志文件alertSID.log中。同时在user_dump_dest下产生了一个跟踪文件,详细描述死锁的相关信息。

在日常工作中,如果发现在日志文件中记录了ora-00060的错误信息,则表明产生了死锁。这时需要找到对应的跟踪文件,根据跟踪文件的信息定位产生的原因。

1.5与锁相关的数据字典视图

2 数据字典视图说明

视图名

描述

主要字段说明

v$session

查询会话的信息和锁的信息。

sid,serial#:表示会话信息。

program:表示会话的应用程序信息。

row_wait_obj#:表示等待的对象,和dba_objects中的object_id相对应。

v$session_wait

查询等待的会话信息。

sid:表示持有锁的会话信息。

Seconds_in_wait:表示等待持续的时间信息

Event:表示会话等待的事件。

v$lock

列出系统中的所有的锁。

Sid:表示持有锁的会话信息。

Type:表示锁的类型。值包括TM和TX等。

ID1:表示锁的对象标识。

lmode,request:表示会话等待的锁模式的信

息。用数字0-6表示,和表1相对应。

dba_locks

对v$lock的格式化视图。

Session_id:和v$lock中的Sid对应。

Lock_type:和v$lock中的type对应。

Lock_ID1: 和v$lock中的ID1对应。

Mode_held,mode_requested:和v$lock中

的lmode,request相对应。

v$locked_object

只包含DML的锁信息,包括回滚段和会话信息。

Xidusn,xidslot,xidsqn:表示回滚段信息。和

v$transaction相关联。

Object_id:表示被锁对象标识。

Session_id:表示持有锁的会话信息。

Locked_mode:表示会话等待的锁模式的信

息,和v$lock中的lmode一致。

 

1.6死锁

当两个用户希望持有对方的资源时就会发生死锁。即两个用户互相等待对方释放资源,oracle认定为产生了死锁,在这种情况下,将以牺牲一个用户作为代价,另一个用户继续执行,牺牲的用户的事务将回滚。

ORA-00060的错误并记录在数据库的日志文件alertSID.log中。同时在user_dump_dest下产生了一个跟踪文件,详细描述死锁的相关信息。

1.7解锁及Kill Session

使用下面的语法查出锁并杀掉Session。

SELECT A.SID,A.SERIAL#,A.USERNAME,B.TYPE FROM V$SESSION A,V$LOCK B WHERE A.SID=B.SID;

ALTER SYSTEM KILL SESSION 'SID,SERIAL#';

1.8预防死锁

避免应用不运行长事务。

经常提交以避免长时间锁定行。

避免使用LOCK命令锁定表。

在非高峰期间执行DDL操作。

在非高峰期间执行长时间运行的查询或事务。

确保开发人员使用限制最少的锁模式比不过仔细设计防止锁争用的事务,

监控阻塞其他锁的锁并调查为什么这些锁正被保持。

确定为什么阻塞的锁的被保持了很长时间并尽量阻止它们。

监视死锁发生的频率并解决它们。

当死锁发生通过回滚事务rollback或者终止会话来解决它。

1.9数据库自动管理锁演示

  1. 在chiikin用户下创建tb1表(图1.9-1),然后执行insert语句(图1.9-2)。

 

图 1.9-1

 

图1.9-2

 

图1.9-3

 

图1.9-4

  1. 在执行图1.9-1的语句后commit前,用sys用户登录(图1.9-3)并查询tb1表(图1.9-4)。在此我们可以看到在chiikin用户插入后但未提交的情况下并没有给tb1加排它锁。其他用户仍能查询。

3)提交(图1.9-5)后,sys用户查询tb1表(图1.9-6)

  

图1.9-5 图1.9-6

3)在chiikin用户下执行更新语句update(图1.9-7)

 

图1.9-7

  1. 与此同时sys用户下执行update语句时id=1的行被锁定而无法更新(图1.9-8)。

 

图1.9-8

 

 

 

  • 序列

2.1什么是序列

在Oracle中,序列是一个对象,可以产生等差变化的值。在不考虑上限或下限的情况下可以保证生成的每一个值都不相同,即不会重复生成。序列是数据库的公共对象,并不属于哪一张表或哪一个用户,任何一个有权限对它引用或修改的用户都可以使用。

2.2使用范围

  1. 生成唯一主键,即当某表需要自动生成唯一值作为主键时可以使用。
  2. 任何需要生成唯一值的地方,特例除外。
  3. 需要数字自动增长或递减的地方。
  4. 多表联合唯一值,即当多个表中的多个列需要协调产生不同的唯一值时可以使用。例如,有多张表每张表保存着不同事物的信息,当需要为这些表中每一个事物生成一个唯一的编号时,即每一张表中的某一公共列中的值与其他表都不同。

2.3创建序列

CREATE SEQUENCE 序列名

[INCREMENT BY n]

[START WITH n]

[{MAXVALUE n |

NOMAXVALUE}]

[{MINVALUE n |

NOMINVALUE}]

[{CYCLE | NOCYCLE}]

[{CACHE n | NOCACHE}];

序列名

是序列生成器(对象)的名称。

INCREMENT BY n

指定序列号的间隔值,其中 n 为

整数(如果省略该语句,序列将

以 1 递增)。若n为负数则递减。

START WITH n

指定要生成的第一个序列号(如果

省略该语句,序列将从 1 开始)。

MAXVALUE n

指定序列可以生成的最大值。

NOMAXVALUE

指定使用默认值:递增序列的最大值为 10^27,递减序列的最大值为-1。

MINVALUE n

指定序列的最小值。

NOMINVALUE

指定默认情况下,递增序列的最

小值为 1,递减序列的最小值为

–(10^26)。

CYCLE |

NOCYCLE

 

指定当序列达到其最大值或最小值

后,是否继续生成值,NOCYCLE

是默认选项。Cycle之循环生成

CAHCE n |

NOCACHE

指定 Oracle 服务器预先分配并保

留在内存中的值的个数。(默认

情况下,Oracle 服务器缓存 20 个

值。)如果系统崩溃,这些值将

丢失。

例子:

CREATE SEQUENCE seq1

INCREMENT BY 1

START WITH 1

MAXVALUE 50000

NOCACHE

NOCYCLE;

说明:该语句创建了一个名为seq1的序列,第一序列值为1,之后的值为递增1,而生成的值得最大值为50000.且当生成的值超过50000后将不再生成值,也不预先把将要生成的值存入内存。

2.4使用序列

1)序列的两个伪列

Nextval:创建序列后第一次使用时返回的是序列的初始值,之后则是按步长递增后的值。

Currval:返回当前序列的值。即最后一次使用Nextval产生的值。

  1. 使用方法:

序列名.nextval 、序列名.currval 。

2.5使用序列的注意事项

  1. 在使用currval获取当前值前必须执行过一次nextval。因为在没有执行过nextval时,currval是不存在的;当nextval被运行过一次后,序列便存在了当前值。
  1.  NEXTVAL 和CURRVAL的可以使用范围:

• 不属于子查询的 SELECT 语句的 SELECT 列表

• INSERT 语句中子查询的 SELECT 列表

• INSERT 语句的 VALUES 子句

• UPDATE 语句的 SET 子句

  1. NEXTVAL 和CURRVAL的不可以使用范围:

• 视图的 SELECT 列表

• 带有 DISTINCT 关键字的 SELECT 语句

• 带有 GROUP BY、HAVING 或 ORDER BY 子句的 SELECT 语句

• SELECT、DELETE 或 UPDATE 语句中的子查询

• CREATE TABLE 或 ALTER TABLE 语句中的 DEFAULT 表达式

2.6修改序列

ALTER SEQUENCE 序列名

 

百度文库 - 让每个人平等地提升自我[INCREMENT BY n]

[{MAXVALUE n |

NOMAXVALUE}]

[{MINVALUE n |

NOMINVALUE}]

[{CYCLE | NOCYCLE}]

[{CACHE n | NOCACHE}];

修改语法与创建语法大致相同,只不过是把create改成了alter。但是修改却不是想象中的那么随意。修改序列有以下限制。

  1. 不能修改序列初始值,即START WITH选项
  2. 修改的最大值(最小值)不允许比当前序列值小(大)。若想修改该选项必须先删除再重新创建。
  3. 需要拥有对欲修改序列的ALTER权限

2.7删除序列

DROP SEQUENCE 序列名;

删除序列后,将无法再对该序列引用。且必须拥有对该序列的drop权限。

2.8序列的高级应用举例

有日期区分的序列

格式:序列值(m+n位)=日期(m位)+ 可循环序列号(n位)

需求:当日期变更后可循环序列号重新从0开始。

如:201405060000~201405065216

201405070000~201405071556

解决方案:

创建一个存储过程,该存储过程实现序列的重建,并利用数据库任务机制,创建一个可以执行存储过程的任务,并按时执行该任务。

 

  • 索引管理

3.1什么是索引

索引是对数据库表中的一列或多列的值进行排序的结构,以达到快速搜索的目的。在Oracle中Oracle server索引是一个方案对象,它使用指针来加速对行的检索。可以显式创建索引,也可以自动创建索引。如果所选择的列上没有索引,则会执行全表扫描。使用索引可以直接并快速的访问表中的行。使用索引是为了减少必需的磁盘 I/O(输入/输出),即通过一个带索引的路径来快速查找数据。创建索引后,用户就不需要再执行直接的操作了。ROWID 是代表行地址的 base 64 字符串,其中包含块标识符、行在块中的位置和数据库文件标识符。索引使用 ROWID 是因为ROWID 是访问任何特定行的最快捷方法。

索引在逻辑和物理形式上都独立于索引基于的表。这意味着可以在任何时候创建或删除索引,而不会对基表或其它索引产生任何影响。

3.2索引类型

1)唯一索引:如果在表中定义的列具有“主键”(PRIMARYKEY) 或“唯一键”(UNIQUE KEY) 约束条件,则 Oracle Server 会自动创建此类型的索引。索引的名称与该约束条件的名称相同。虽然可以手动创建唯一索引,但是建议您在表中创建唯一约束条件,从而隐式创建唯一索引。

2)非唯一索引:这是由用户创建的用于加快行访问速度的索引。例如,要优化联接,可以在“外键”(FOREIGN KEY) 列上创建索引,这样会加快索与主键列匹配的行的速度。

除上述两种索引外还可以细分出一下几种索引:

3)组合索引

组合索引(也称为“级连”索引)是指对表中的多个列创建的索引。组合索引中的各列可以按任意顺序出现,不需要在表中相邻。

4)基于函数的索引

基于函数的索引将存储建立索引的值,并使用基于 SELECT 语句的索引检索数据。基于函数的索引是基于表达式的索引。索引表达式是用表列、常数、SQL 函数和用户定义的函数构建的。

  1. 位图索引

位图索引使用位图作为键值,对于表中的每一数据行位图包含了少量的有限个值,当时行查询时,位图索引通过不同位图取值直接的位运算(与或),来获取到结果集合向量(计算出的结果)。当时行查询时,位图索引通过不同位图取值直接的位运算(与或),来获取到结果集合向量(计算出的结果)。。当列中有非常多的重复的值时候,例如某列保存了 “性别”信息;Where 条件中包含了很多OR操作符时可以使用。

还有其他索引,在此不再过多介绍。如,B-树索引、HASH索引、索引编排表、反转键索引、分区索引、本地和全局索引。

3.3创建索引

索引的创建语法:

CREATE UNIUQE | BITMAP INDEX <schema>.<index_name>

ON <schema>.<table_name>

 (<column_name> | <expression> ASC | DESC,

 <column_name> | <expression> ASC | DESC,...)

TABLESPACE <tablespace_name>

STORAGE <storage_settings>

LOGGING | NOLOGGING

COMPUTE STATISTICS

NOCOMPRESS | COMPRESS<nn>

NOSORT | REVERSE

PARTITION | GLOBAL PARTITION<partition_setting>

说明:

1)UNIQUE | BITMAP:指定UNIQUE为唯一值索引,BITMAP为位图索引,省略为B-Tree索引。

2)<column_name> | <expression> ASC | DESC:可以对多列进行联合索引,当为expression时即“基于函数的索引”

3)TABLESPACE:指定存放索引的表空间(索引和原表不在一个表空间时效率更高)

4)STORAGE:可进一步设置表空间的存储参数

5)LOGGING | NOLOGGING:是否对索引产生重做日志(对大表尽量使用NOLOGGING来减少占用空间并提高效率)

6)COMPUTE STATISTICS:创建新索引时收集统计信息

7)NOCOMPRESS | COMPRESS<nn>:是否使用“键压缩”(使用键压缩可以删除一个键列中出现的重复值)

8)NOSORT | REVERSE:NOSORT表示与表中相同的顺序创建索引,REVERSE表示相反顺序存储索引值

9)PARTITION | NOPARTITION:可以在分区表和未分区表上对创建的索引进行分区

简单例子:

Create index ind1 on tb1(id);

Create index ind2 on tb1(id,name);

Create bitmap index ind3 tb3(sex);

3.4建立索引的注意事项

  1. 应该建立索引的情况:

·列中值的范围很大

·列包含大量 null 值

·在 WHERE 子句或联接条件中频繁使用一个列或多个列的组合

·表很大,但是预计大多数查询要检索的行不到总行数的 2-4%

  1. 不建议建立索引的情况:

• 表太小

• 在查询中没有频繁用作条件的列

• 预计大多数查询要检索的行超过表中总行数的 2-4%

• 表更新频繁

• 表达式中引用了用作索引的列

3) 使用IS NULL 或IS NOT NULL

使用IS NULL 或IS NOT NULL同样会限制索引的使用。因为NULL值并没有被定义。在SQL语句中使用NULL会有很多的麻烦。因此建议开发人员在建表时,把需要索引的列设成NOT NULL。如果被索引的列在某些行中存在NULL值,就不会使用这个索引(除非索引是一个位图索引)。

3.5 组合索引

当某个索引包含有多个已索引的列时,称这个索引为组合(concatented)索引。在Oracle9i引入跳跃式扫描的索引访问方法之前,查询只能在有限条件下使用该索引。比如:表emp有一个组合索引键,该索引包含了empno、ename和deptno。在Oracle9i之前除非在where之句中对第一列(empno)指定一个值,否则就不能使用这个索引键进行一次范围扫描。

3.6基于函数的索引

可以在表中创建基于函数的索引。如果没有基于函数的索引,任何在列上执行了函数的查询都不能使用这个列的索引。例如,下面的查询就不能使用JOB列上的索引,除非它是基于函数的索引:

select * from emp where UPPER(job) = 'MGR';

下面的查询使用JOB列上的索引,但是它将不会返回JOB列具有Mgr或mgr值的行:

select * from emp where job = 'MGR';

可以创建这样的索引,允许索引访问支持基于函数的列或数据。可以对列表达式UPPER(job)创建索引,而不是直接在JOB列上建立索引,如:

create index EMP$UPPER_JOB on emp(UPPER(job));

尽管基于函数的索引非常有用,但在建立它们之前必须先考虑下面一些问题:

能限制在这个列上使用的函数吗?如果能,能限制所有在这个列上执行的所有函数吗

是否有足够应付额外索引的存储空间?

在每列上增加的索引数量会对针对该表执行的DML语句的性能带来何种影响?

基于函数的索引非常有用,但在实现时必须小心。在表上创建的索引越多,INSERT、UPDATE和DELETE语句的执行就会花费越多的时间。

注意:对于优化器所使用的基于函数的索引来说,必须把初始参数QUERY _REWRITE _ ENABLED设定为TRUE。

3.7删除索引

不能修改索引。要更改索引,必须先将其删除,然后重新创建。通过发出 DROP INDEX 语句,可以从数据字典中删除索引定义。要删除索引,您必须是该索引的所有者或有 DROP ANY INDEX 权限。如果删除了一个表,则会自动删除其索引和约束条件,不过会保留视图和序列。

语法:DROP INDEX 索引;

 

Guess you like

Origin blog.csdn.net/wangbaosongmsn/article/details/117422516