Oracle 事务 锁
一、 事务
是一系列的数据库操作,是数据库应用的基本逻辑单位以及并发控制的基本单位。所谓的事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。
要将有组语句作为事务考虑,就需要通过ACID测试,即原子性,一致性,隔离性和持久性。
1. 事务性质
原子性、一致性或可串性、隔离性、持久性
▶ 原子性Atomic:即不可分割性,事务要么全部被执行,要么就全部不被执行。
▶ 一致性或可串性Consistency:事务的执行使得数据库从一种正确状态转换成另一种正确状态。
▶隔离性Isolation:事务允许多个用户对同一个数据进行并发访问,而不破坏数据的正确性和完整性。同时,并行事务的修改必须与其他并行事务的修改相互独立。在事务正确提交之前,不允许把该事务对数据的任何改变提供给任何其他事
▶ 持久性Durability:事务正确提交后,其结果将永久保存在数据库中,即使在事务提交后有了其他故障,事务的处理结果也会得到保存。
2. 事务语句
▶ 开始事物:begin transaction
▶ 提交事物:commit transaction
▶ 回滚事务:rollback transaction
用户在事务(transaction)内可以声明(declare)被称为保存点(savepoint)的标记。保存点将一个大事务划分为较小的片断。
▶ save transaction 保存点名称 --自定义保存点的名称和位置
▶ rollback transaction 保存点名称 --回滚到自定义的保存点
用户可以使用保存点(savepoint)在事务(transaction)内的任意位置作标记。之后用户在对事务进行回滚操作(rolling back)时,就可以选择从当前执行位置回滚到事务内的任意一个保存点。
3. 事务使用
① 创建一张表以作示例
-- 建表 create table student(
id varchar2(4),
name varchar2(100), --姓名
sex varchar2(1), --性别 1 男 2 女 0 未知
score integer default 0
); select * from student; -- 插入数据 insert into student (id, name, sex)values ('', '大王', '');
insert into student (id, name, sex)values ('', '刘一', '');
insert into student (id, name, sex)values ('', '陈二', '');
insert into student (id, name, sex)values ('', '张三', '');
insert into student (id, name, sex)values ('', '李四', '');
insert into student (id, name, sex)values ('', '王五', '');
insert into student (id, name, sex)values ('', '赵六', '');
insert into student (id, name, sex)values ('', '孙七', '');
insert into student (id, name, sex)values ('', '周八', '');
insert into student (id, name, sex)values ('', '吴九', '');
insert into student (id, name, sex)values ('', '郑十', '');
commit;
② 以上表为基础的一个事务示例
CREATE OR REPLACE PROCEDURE p_transaction_test(p_error_no out int, --错误编号
p_error_info out varchar2 --错误信息
) as begin
/*
wangrui 事务commit测试
①处commit:第一条更新成功,第二条更新失败,回滚;由于第二条失败时,第一条已经提交。
②处commit;第一条更新失败,第二条更新失败;由于没有提交,第二条失败,语句还没到②commit处已经回滚,两条均未更新。
③处commit;在此,跟②处的结果是一样的,是对事物最后的提交。 Ⅰ处savepoint会使事务回滚到A为止,如果此时①处有commit,会导致Ⅰ保存点失效,报错,但是事务会回滚到①提交处
Ⅱ处savepoint会使事务回滚到B位置
注意:roll rollback to savepoint之后需要commit。否则事务回到savepoint之后,savepoint之前的获得的锁并未被释放 一般使用commit提交即可,不使用savepoint。
……
*/ p_error_no := 0;
p_error_info := ' ';
begin --Ⅰ
--savepoint save1; update student set sex = '' where id = ''; --一条会成功更新的SQL语句 --①
commit;
--Ⅱ
--savepoint save1; update student set sex = '' where id = ''; --一条语句超长,更新失败的SQL语句 --②
--commit; exception
when others then
rollback --to savepoint save1;commit
;
p_error_no := -1;
p_error_info := '失败:' || SQLERRM;
return;
end; --③提交事务
commit; end;
二、 事务的隔离级别
1. 事务并发访问时存在的问题
▶ 脏读:如果一个事务读取的记录是另一个未完成事务的一部分,就发生了脏读。如果第一个事务正常完成,就没有什么问题。但是,如果前一个事务回滚了,那将从数据库从未发生的事务中获取了信息。
▶ 不可重复读取:很容易将不可重复性读取和脏读混淆。如果一个事务中两次读取记录,而另一个事务在这期间改变了数据,就会发生不可重复性读取。
▶ 幻读:如果一个事务读取一个记录,返回结果集,此时,另一个事务插入一条记录并提交
2. 事务的隔离级别
3. ORACLE支持的事务隔离级别
只读模式:只读事务只能看到事务执行前就已经提交的数据,且事务中不能执执行 INSERT , UPDATE ,及 DELETE 语句
已提交读取:Oracle 默认使用的事务隔离级别。事务内执行的查询只能看到查询执行前(而非事务开始前)就已经提交的数据。Oracle 的查询永远不会读取脏数据(未提交的数据)。
Oracle 不会阻止一个事务修改另一事务中的查询正在访问的数据,因此在一个事务内的两个查询的执行间歇期间,数据有可能被其他事务修改。举例来说,如果一个事务内同一查询执行两次,可能会遇到不可重复读取或不存在读取的现象。
串行化:串行化隔离的事务只能看到事务执行前就已经提交的数据,以及事务内 INSERT , UPDATE ,及 DELETE 语句对数据的修改。串行化隔离的事务不会出现不可重复读取或不存在读取的现象。
--只允许select操作,不允许有任何修改数据库(包括 insert、update、delete)中数据的操作语句,允许创建语句create
set transaction read only;
--默认设置,表示在事务中可以有访问语句、修改语句(包括insert、delete、update),允许创建语句create,同read committed
set transaction read write;
--同read write;
set transaction isolation level read committed;
--serialzable可以执行DML操作
set transaction isolation level serializable;
3.1 read only
新建一个事务如下
set transaction read only;
① 执行
select * from student;
② 执行
update student set score = 100 where id = '0002';
3.2 read write
① 新建一个事务如下
set transaction read write;
② 执行
select * from student;
② 执行
update student set score = 100 where id = '0002';
select * from student;
结论:允许读写(包括insert、delete、update)
3.3 isolation level read committed(可幻读和重复读)
新建两个事务如下
① 新建事务T1
set transaction read write;
select * from student;
② 新建事务T2
set transaction isolation level read committed;
select * from student;
③ 在事务T1中修改ID=002的记录并commit;
update student set score = 100 where id = '0002';--未commit状态下在T2事务中并未看到更新
commit;
④ 在事务T2 中查看commit后的结果如下(commit状态下看到更新结果)
select * from student;
⑤ 在事务T1中删除ID=003的记录, 并commit;
delete from student where id='0003';--未commit时在T2中还可以看到该条记录
commit;
⑥ 在事务T2 中查看commit后的结果如下(commit之后看不到该条记录)
⑦ 在事务T1中插入ID=0006的记录,并commit;
insert into student (id, name, sex)values ('0006', '王五', '0');--未commit之前在T2中看不到该条记录
commit;
⑧ 在事务T2 中查看commit后的结果如下(commit之后看到该条记录已经添加)
结论:①-⑥ 说明事务隔离级别为isolation level read committed时,允许可重复读。
⑦-⑧ 说明事务隔离级别为 isolation level read committed, 允许幻想读
3.4 isolation level serializable
创建了两个事务如下
① 新建事务T1
set transaction read write;
select * from student;
② 新建事务T2
set transaction isolation level serializable;
select * from student;
③ 在事务T1中修改ID=002的记录并commit;
update student set score = 100 where id = '0002';--未commit状态下在T2事务中并未看到更新
commit;
④ 在在事务T2 中查看commit后的结果如下(commit状态下也没有看到更新)
⑤ 在事务T1中删除ID=003的记录, 并commit;
delete from student where id='0003';--未commit时在T2中还可以看到该条记录
commit;
⑥ 在事务T2 中查看commit后的结果如下(commit状态下依然可以看到该条记录)
⑦ 在事务T1中插入ID=0006的记录,并commit;
insert into student (id, name, sex)values ('0006', '王五', '0');--未commit之前在T2中看不到该条记录
commit;
⑧ 在事务T2 中查看commit后的结果如下(commit状态下依然看不到该条记录)
结论:①-⑥ 说明事务隔离级别为isolation level serializable时,不支持可重复读。
⑦-⑧ 说明事务隔离级别为 isolation level serializable 时, 不支持幻想读
三、 锁
锁是一种机制,多个事务同时访问一个数据库对象时,该机制可以实现对并发的控制
ORCLE 多事务并发可能存在的问题
丢失更新:丢失更新发生在一个更新成功写入数据库后,而又意外地被另一个事务重写时。这是怎么发生的呢?如果有两个事务读取整个记录,然后其中一个向记录写入了更新信息,而另一个事务也向该记录写入更新信息,这是就会出现丢失更新。
1. oracle 中锁的类型
① DML锁(data locks,数据锁),用于保护数据的完整性。oracle自动的施加和释放。
② DDL锁(dictionary locks,字典锁),用于保护数据库对象的结构,如表、索引等的结构定义. 事务开始时施加,使用Commit后者Rollback被释放。
③ 内部锁和闩(internal locks and latches),保护数据库的内部结构。由oracle自己管理以保护内部数据库结构。
2. 锁的粒度
① 行级锁(TX):阻止该行上的DML操作,直到Commit或者Rollback。
② 表级锁(TM):
③ 数据库级锁::
eg:将数据库锁定为只读模式 alter database open read only;
eg:将数据库设置为限制模式(导入导出数据库时使用):alter system enable restricted session;
3. oracle 中锁的模式
3.1 锁的模式
3.2 锁的兼容性
3.3 锁表语句
lock table student in row share mode;
lock table student in row exclusive mode; --用于行的修改
lock table student in share mode; --阻止其他DML操作
lock table student in share row exclusive mode; --阻止其他事务操作
lock table student in exclusive mode; --独立访问使用
4. 锁的查看
① 创建一个事务,执行
update student set score=888 WHERE ID='0004';
② 执行
select * from v$locked_object; --object_id为表名
③ 执行
select s.sid, s.serial#, s.username, s.schemaname, s.osuser, s.process, s.machine, s.terminal, s.logon_time, l.type, l.lmode
from v$session s, v$lock l
where s.sid = l.sid
and s.sid= ''
order by sid;
如图,DML操作,获得一个TM锁,还获得一个TX锁,还有一个……,故而其他事务可以对该表的其他行进行编辑,但是0004行不允许其他事务有任何操作。
我们可以认为Oracle 6种MODE的锁,根据锁定的对象不同而有不同的名称,如6号的X锁,既可以是用于锁表的TM锁,也可以是TX锁,也可以是DDL锁。
四、 死锁
如果一个锁由于另一个锁占有资源而不能完成应该做的工作,就会导致死锁;反之亦然。
1 死锁产生条件
① Mutual exclusion(互斥):资源不能被共享,只能由一个进程使用。
② Hold and wait(请求并保持):已经得到资源的进程可以再次申请新的资源。
③ No pre-emption(不可剥夺):已经分配的资源不能从相应的进程中被强制地剥夺。
④ Circular wait(循环等待条件):系统中若干进程组成环路,该环路中每个进程都在等待相邻进程正占用的资源。
2. 死锁模拟
① 查看表内容
select * from student;
② 新建一个事务T1,执行
update student set score=111 WHERE ID='0002';
未提交状态下提示一行被更新
③ 新建一个事务T2,执行
update student set score=333 WHERE ID='0003';
未提交状态下提示一行被更新
④ 在事务T1中执行
update student set score=222 WHERE ID='0003';
显示“正在执行……”表示等待中
⑤ 在事务T2中执行
update student set score=444 WHERE ID='0002';
此时,事务T2显示“正在执行……”表示等待,T1事务是提交或者回滚状态
⑥ commit 事务T1
显示事务T1只更新了0002,0003并未更新成功。
⑦ commit 事务T2,然后查看结果
显示事务T2更新了0002,0003,相当于事务T1的结果丢失了。
3. 解决死锁冲突
在没有执行⑥⑦操作的情况下
新⑥ 执行
select sid,serial#,username from v$session where sid in (select blocking_session from v$session);
alter system kill session '1522,42255';
第一行代码找到sid='1522,serial#=42255'
第二行代码杀掉这个堵塞的进程
新⑦ 此时,提交进程事务T1,结果显示。
新⑧ 提交事务T2,显示提交成功,查看结果
显示事务T2更新了0002,0003,相当于事务T1的结果丢失了。
结论:oracle在死锁情况下,会保存后面一个事务的更新结果。
4. 事务和死锁预防总结
① 避免应用不运行长事务。
② 经常提交以避免长时间锁定行。
③ 避免使用LOCK命令锁定表。
⑤ 在高峰期间执行DDL操作,在非高峰期间执行长时间运行的查询或事务。
Oracle 事务 锁的更多相关文章
- oracle 事务 锁机制
原文地址:http://www.cnblogs.com/quanweiru/archive/2013/05/24/3097367.html 本课内容属于Oracle高级课程范畴,内容略微偏向理论性,但 ...
- Oracle事务之一:锁和隔离
Oracle事务之一:锁和隔离 一. 事务概述 事务管理是数据库处理的核心.数据库既要保证用户能并发地执行事务,还要保证数据库的一致性. 当第一条可执行的SQL开始执行,就隐形地开始了一个事务,直到遇 ...
- oracle事务和锁
数据库事务概括 1. 说明 一组SQL,一个逻辑工作单位,执行时整体修改或者整体回退. 2.事务相关概念 1)事务的提交和回滚:COMMIT/ROLLBACK 2)事务的开始和结束 开始事务:连接到数 ...
- oracle事务和锁(转)
If you use a SET TRANSACTION statement, then it must be the first statement in your transaction. How ...
- Oracle事务与锁
Oracle事务与锁 2017-12-13 目录 1 数据库事务概括 1.1 事务定义 1.2 事务生命周期 1.3 事物的特性 1.4 死锁2 事务相关语句 2.1 事务相关语句概括 2 ...
- Oracle事务和锁机制
事务 1. 说明 一组SQL,一个逻辑工作单位,执行时整体修改或者整体回退. 2.事务相关概念 1)事务的提交和回滚:COMMIT/ROLLBACK 2)事务的开始和结束 开始事务:连接到数据库,执行 ...
- 从浅到深掌握Oracle的锁
1.分别模拟insert,update和delete造成阻塞的示例,并对v$lock中的相应的信息进行说明,给 出SQL演示. Insert示例 会话:SQL> select * from ...
- Oracle基础 锁
一.锁 数据库是一个多用户使用的共享资源.当多个用户并发地存储数据时,数据库中就会产生多个事务同时存取同一数据的情况.若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性. 锁是实现 ...
- oracle事务(转)
今天温习oracle事务,记录如下: 事务定义 事务是保持数据的一致性,它由相关的DDL或者DML语句做为载体,这组语句执行的结果要么一起成功,要么一起失败. 我们 ...
随机推荐
- E 聪明的“KK”
Description 非洲某国展馆的设计灵感源于富有传奇色彩的沙漠中陡然起伏的沙丘,体现出本国不断变换和绚丽多彩的自然风光与城市风貌.展馆由五部分组成,馆内影院播放名为<一眨眼的瞬间>的 ...
- > Task :app:transformDexArchiveWithExternalLibsDexMergerForDebug FAILED
> Task :app:transformDexArchiveWithExternalLibsDexMergerForDebug FAILED D8: Cannot fit requested ...
- 因为.patch_storage目录丢失,导致opatch打补丁失败
一套新装的ORACLE Restart环境(11.2.0.3.0),计划最新的PSU,在使用opath auto方式安装补丁时报错,表面上的错误信息提示opatch工具不满足版本要求: [root@d ...
- Retina显示屏-揭秘移动端的视觉稿通常会设计为传统PC的2倍
一.Retina显示屏简介 retina:一种具备超高像素密度的液晶屏,同样大小的屏幕上显示的像素点由1个变为多个,如在同样带下的屏幕上,苹果设备的retina显示屏中,像素点1个变为4个. reti ...
- c#文件相关笔记
1.将*.txt文件内容转换为一个字符串str FileStream fs = new FileStream("路径\\*.txt", FileMode.Open); Stream ...
- varnish与squid的比较
生产环境中尝试使用varnish替代squid的主要原因: 1. squid不支持多核cpu, 生产环境中大多使用Dell R610系列,这种类型机器配置为2个4核双线程cpu, 操作系统识别为16个 ...
- c#写word文档基础操作(自己控制样式)
下面一个函数,建立一个Word 文档,添加页眉.页脚,在内容中两个不同字体的Hello!!! 来自 <http://bbs.csdn.net/topics/340041961> pub ...
- html5标签的兼容性处理
HTML5的语义化标签以及属性 1.可以让开发者非常方便地实现清晰的web页面布局,加上CSS3的效果渲染,快速建立丰富灵活的web页面显得非常简单 2.使用他们能让代码语义化更直观,而且更方便SEO ...
- 添加SAP_ALL权限
更新usr04,ust04,usrbf2这三张表 REPORT ZTESTCREATEUSER. data: l_USR04 LIKE USR04 , l_UST04 LIKE UST04 , l_P ...
- uLua学习之调用Lua函数(五)
前言 在我开始这个系列的第一篇文章中,我就提到了Lua脚本用来实现宿主脚本的配置性和扩展性.上节说到的调用外部Lua脚本就对应了它的两大特性之一的配置性,那么另一大特性如何来体现呢?这就要说我们今天的 ...