Oracle中事务处理和锁定

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chengyunyi123/article/details/67634376

1.什么是事务?

事务是一个由多条SQL语句组成的工作逻辑单元,这些语句要么全部执行,要么不执行,只要有一条SQL语句执行失败,则已执行的SQL语句会回滚到执行之前的状态,这样就保证了数据库数据的一致性,不产生混乱的数据信息。

2.事务必须满足ACID

ACID即,原子性,一致性,隔离性,持久性。
在PL/SQL进行程序设计时,不需要显示地使用事务语句开始一个事务,当遇到第一个DML语句时,一个事务开始,在出现下列情况时,事务结束:

遇到COMMIT语句或ROLLBACK语句时,将提交或者回滚事务。
当用户退出Oracle工具时,比如退出SQL*PLUS或Toad时。
当机器失效或系统崩溃时。

3.PL/SQL提供以下语句用于事务的管理

1)COMMIT:保存自上一次COMMIT或ROLLBACK以来的所有改变,并且释放所有的锁。

语法:COMMIT [WORK] [COMMENT text];

可选的关键字WORK仅为了增强可读性,并没有任何其他作用;可选的关键字COMMENT用来为某个分布式事务添加注释,如果在COMMIT时出现网络或机器故障,Oracle会在数据字典中保存COMMENT关键字提供的文本内容和相关的事务ID,文本内容必须是用引号括起来的长度不超过50个字符的文字。

2)ROLLBACK:回滚所有自上一次COMMIT或ROLLBACK以来的所有改变,并且释放所有该范围的锁。

3)ROLLBACK TO SAVEPOINT:回滚所有的改变到一个已经保存的保存点,并且释放该范围内的锁。

语法:ROLLBACK [WORK] [TO [SAVEPOINT] savepoint_name];

WORK只是为了增强可读性,TO子句用于回滚到特定的保存点,如果在ROLLBACK时,不指定任何参数,将回滚当前事务的所有更改。

如果说COMMIT就好比保存操作的话,那么ROLLBACK就好比撤销操作。使用ROLLBACK一般有如下两大情形:
1.误删了数据或更改了错误的数据,使用回滚能帮助恢复原始的数据。

2.如果触发了一个异常或者SQL语句执行失败而不能完成事务,使用回滚能将数据恢复到初始状态,以便于再次执行。

4)SQVEPOINT:建立一个保存点,允许完成局部的回滚操作。

语法:SAVEPOINT savepoint_name;

savepoint_name是保存点的名字,命名必须遵循SQL标识符的一般规则。一旦定义了保存点,那么就可以使用ROLLBACK TO SAVEPOINT这样的语句来撤销特定的保存点。ROLLBACK TO SAVEPOINT命令执行之后,将会发生以下事情:
1)从保存点以后所做的工作都被撤销,但是保存点未被释放,如果需要,可以再次撤销该保存点。
2)自该保存点以后SQL语句所需的锁和资源都被释放。
3)虽然撤销到保存点,但是并不是结束整个事务,SQL语句处于挂起状态。

5)SET TRANSACTION:允许开始一个只读或读写会话,建立一个隔离级别,或者是将当前事务赋给一个特定的回滚段。

SET TRANSACTION语句允许开始一个只读或只写的事务,建立隔离级别或者是为当前事务分配一个特定的回滚段。

• SET TRANSACTION必须是事务处理的第1条语句,并且只能出现一次。

语法:SET TRANSACTION paramete

parameter用来指定事务的参数,可供使用的参数取值有如下几种:
1)READ ONLY:建立只读事务,在此事务中执行任何INSERT、DELETE、UPDATE或SELECT FOR UPDATE等命令都属于非法操作,对于这种事务模式不用指定回滚。
2)READ WRITE:建立读写事务,读写事务没有只读事务的种种限制,可以执行CRUD各种语句。
3)ISOLATION LEVEL:用来设置事务的隔离级别,即规定在事务中如何处理DML事务,可以设置SERIALIZABLE和READ COMMITTED这两个选项。SERIALIZABLE选项会使得已修改但没有提交的数据库对象的DML事务失败,READ COMMITTED选项会使得对已经修改但没有提交的数据库对象的DML事务进行修改时,会等待前面的DML锁消失,这时ORACLE的默认特性。ISOLOATION LEVEKL的基本使用语法如下:
SET TRANSACTION ISOLATION ISOLATION LEVEL SERIALIZABLE; –设置序列隔离级别
SET TRANSATION ISOLATION READ COMMITTED; –设置读提交隔离级别

USE ROLLBACK SEGMENT:给事务定义一个合适的回滚段,基本语法如下所示:
SET TRANSATION ISOLATION USE ROLLBACK SEGMENT segmentname ;

在使用只读事务时,只有SELECTINTO、OPEN、FETCH、CLOSE、LOCK TABLE、COMMIT和ROLLBACK语句才允许出现在只读事务中,并且查询过程不能使用FOR UPDATE。

6)LOCK TABLE:允许使用特定的模式锁定整个数据库表,这将覆盖默认的行级别的锁定。

锁定是数据库管理系统确保数据一致性和完整性的重要机制

LOCK TABLE语句允许用户使用一个特定的锁定模式锁定整个数据表,使用LOCK TABLE允许开发人员在某一操作之前共享或拒绝其他用户对于该表的访问。LOCK TABLE语句的语法如下:

LOCK TABLE table_reference_list IN lock_mode MODE [NOWAIT];

语句中的table_reference_list是一个或多个所引用的数据表的列表,Lock_mode就是几种锁定的模式,NOWAIT是可选项,当试图锁定一个表的时候,如果该表已被别的事务锁定,则立即将控制返还给事务。

如果要解除使用LOCK TABLE语句的锁定,只需要简单地使用COMMIT或ROLLBACK语句即可。

使用LOCK TABLE还可以对视图进行锁定,当然锁定视图实际上是对视图所组成的基础表进行了锁定,比如view_emp_dept视图由emp表和dept表组成,那么锁定视图实际上是对emp和dept这两个表的锁定。

Oracle在执行更新或删除操作时,会自动获取行级别的锁,如果要在更新或删除操作执行之前锁住行才使用FOR UPDATE子句。

在Oracle中,锁定又可以分为如下两种类型。
1)表锁定:对整个表实行数据锁定,以确保当前事务可以访问数据,但是防止其他的会话或事务同时对该表进行访问而造成冲突,用于保护整张表的数据。
Oracle默认并不会进行表锁定,但是可以使用LOCK TABLE把整张表用指定的锁模式进行锁定,这样就能共享或拒绝对这些表的访问。
表锁定具有不同的模式,这些模式决定了什么样的锁可以作用于数据表上。例如,如果多个用户同时获取一个表上的行共享锁,但是只能有一个用户获取排他锁,那么其中一个用户获取排它锁时,其他的用户就不能插入、删除或更新表中的数据。

• 表锁定不会阻止用户对表进行查询,而且查询也不会获取表锁。只有两个不同的事务尝试修改同样的数据时,才可能出现其中一个事务等待另一个事务完成的现象。

以下是集中常见的表锁定模式:
• ROW SHARE:行共享锁,这是一种最小限制的锁定,在锁定表的同时允许别的事务并发地对表进行SELECT、INSERT、UPDATE和DELETE及LOCK TABLE操作,它不允许任何事务对同一个表进行独占式的写访问。
• ROW EXCLUSIVE:行排它锁,当一个表的多条记录被更新时,也允许别的事务对同一个表执行SELECT、INSERT、UPDATE和DELETE及LOCK TABLE操作,但是与行共享锁不同的是它不能防止别的事务对同一个表的手工锁定或独占式的读与写。
• SHARE LOCK:共享锁,只允许别的事务查询或锁定特定的记录,防止任何事务对同一个表的插入、修改或删除操作。
• SHARE ROW EXCLUSIVE:共享排它锁,用户查看整个表,也允许别的事务查看表中的记录,但不允许别的事务以共享模式锁定表或更新表中的记录。这种锁定一般只允许用于SELECT FOR UPDATE语句中。
• EXCLUSIVE:排它锁,该事务以独占式写一个表,允许别的用户读取和查询,但是不允许进行任何的INSERET、UPDATE和DELETE工作。

如果没有显示地指定锁定,Oracle在运行会自动地提供隐式的锁定,因此一般情况下不需要对锁进行精细的控制,只有在特殊需要时,才可能需要手工控制锁定的级别。

2)记录锁定:又称为行锁定,对之前操作的一行进行锁定,锁定总是以独占的方式进行,在一个事务结束之前,其他事务将要等待该事务结束。
Oracle隐式地实现记录锁定,当执行INSERT、DELETE及SELECT FOR UPDATE语句时,将进行行记录锁定。这种锁又称为互斥锁,或者也称为排它锁(Exclusive Locks)。当记录添加了这种锁之后,锁定总是以独占的方式进行,一个事务没有结束以前,其他的事务只有等待知道锁定释放。可以用FOR UPDATE语句为记录添加一个排它锁:
SELECT * FROM emp WHERE deptno = 10 FOR UPDATE;
只要添加了FOR UPDATE选项,就会为选中的行添加记录锁,其他的事务要等该事务结束才能修改同样的记录。如果在FOR UPDATE子句后面使用NOWAIT子句,Oracle会马上拒绝而返回ORA-0054异常,提示资源正忙。

猜你喜欢

转载自blog.csdn.net/chengyunyi123/article/details/67634376
今日推荐