重复数据插入unique列时,锁加在哪?
1.测试目的
当插入重复数据到有unique索引的表中时,采用何种加锁机制。
2.测试思路
利用10046确定是什么操作导致加锁阻塞了进程;
dump锁定前最近一次操作的块结构来分析加锁机制。
3.测试环境
SQL> select * from v$version where rownum=1;
BANNER
-----------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
4.测试过程
表test2及其索引idx_test2_id对应的object_id。
SQL> select object_id,object_name from dba_objects where object_name in ('TEST2','IDX_TEST2_ID');
OBJECT_ID OBJECT_NAME
---------- ---------------
27667 TEST2
27668 IDX_TEST2_ID
--session 1
SQL> insert into test2 values(1,'a');
已创建 1 行。
此处不提交。
--session 2
SQL> alter system flush buffer_cache;
系统已更改。
SQL > alter session set events ‘10046 trace name context forever,level 8’;
SQL> insert into test2 values(1,'a');
此处一直处于等待状态。
然后将session 1提交,这时session 2报错。
下面dump片断是在sesson 2处于等待状态时的10046跟踪结果:
=====================
PARSING IN CURSOR #2 len=31 dep=0 uid=34 oct=2 lid=34 tim=10705648912 hv=4047255222 ad='277dc964' sqlid='9u2g41msmsdpq'
insert into test2 values(1,'a')
END OF STMT
PARSE #2:c=15625,e=92942,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,plh=0,tim=10705648905
WAIT #2: nam='db file sequential read' ela= 22644 file#=5 block#=170050 blocks=1 obj#=27667 tim=10705671989
WAIT #2: nam='db file sequential read' ela= 10704 file#=5 block#=170049 blocks=1 obj#=27667 tim=10705682866
WAIT #2: nam='db file sequential read' ela= 299 file#=5 block#=170048 blocks=1 obj#=27667 tim=10705683300
WAIT #2: nam='db file scattered read' ela= 25431 file#=5 block#=170051 blocks=5 obj#=27667 tim=10705708852
WAIT #2: nam='db file sequential read' ela= 13716 file#=3 block#=256 blocks=1 obj#=0 tim=10705722841
WAIT #2: nam='db file sequential read' ela= 15175 file#=3 block#=35109 blocks=1 obj#=0 tim=10705738184
WAIT #2: nam='db file scattered read' ela= 22759 file#=5 block#=170056 blocks=8 obj#=27668 tim=10705775416
WAIT #2: nam='db file sequential read' ela= 14768 file#=3 block#=160 blocks=1 obj#=0 tim=10705790482
*** 2012-06-13 11:15:22.984
WAIT #2: nam='enq: TX - row lock contention' ela= 34452785 name|mode=1415053316 usn<<16 | slot=196626 sequence=906 obj#=0 tim=10740253456
WAIT #2: nam='latch: cache buffers chains' ela= 44613 address=783740924 number=150 tries=0 obj#=0 tim=10740298330
=====================
上面黑体部分,27667是表test2,27668是索引idx_test2_id,这个地方报等待事件“enq: TX - row lock contention”了。
下面这部分片断为session 1提交后,session 2报违反唯一性错误时的10046片断。
=====================
PARSING IN CURSOR #1 len=84 dep=1 uid=0 oct=3 lid=0 tim=10740356283 hv=2686874206 ad='29cece34' sqlid='2skwhauh2cwky'
select o.name, u.name from obj$ o, user$ u where o.obj# = :1 and o.owner# = u.user#
END OF STMT
PARSE #1:c=0,e=916,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,plh=0,tim=10740356276
EXEC #1:c=0,e=2776,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,plh=2024304382,tim=10740359417
WAIT #1: nam='db file sequential read' ela= 8833 file#=1 block#=337 blocks=1 obj#=36 tim=10740368472
WAIT #1: nam='db file sequential read' ela= 18496 file#=1 block#=36489 blocks=1 obj#=36 tim=10740387126
WAIT #1: nam='db file sequential read' ela= 13908 file#=1 block#=35771 blocks=1 obj#=18 tim=10740401184
WAIT #1: nam='db file sequential read' ela= 6505 file#=1 block#=217 blocks=1 obj#=11 tim=10740407986
WAIT #1: nam='db file sequential read' ela= 343 file#=1 block#=210 blocks=1 obj#=22 tim=10740408476
FETCH #1:c=0,e=49001,p=5,cr=5,cu=0,mis=0,r=1,dep=1,og=4,plh=2024304382,tim=10740408587
STAT #1 id=1 cnt=1 pid=0 pos=1 obj=0 op='NESTED LOOPS (cr=5 pr=5 pw=0 time=0 us cost=4 size=45 card=1)'
STAT #1 id=2 cnt=1 pid=1 pos=1 obj=18 op='TABLE ACCESS BY INDEX ROWID OBJ$ (cr=3 pr=3 pw=0 time=0 us cost=3 size=27 card=1)'
STAT #1 id=3 cnt=1 pid=2 pos=1 obj=36 op='INDEX RANGE SCAN I_OBJ1 (cr=2 pr=2 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #1 id=4 cnt=1 pid=1 pos=2 obj=22 op='TABLE ACCESS CLUSTER USER$ (cr=2 pr=2 pw=0 time=0 us cost=1 size=18 card=1)'
STAT #1 id=5 cnt=1 pid=4 pos=1 obj=11 op='INDEX UNIQUE SCAN I_USER# (cr=1 pr=1 pw=0 time=0 us cost=0 size=0 card=1)'
CLOSE #1:c=0,e=341,dep=1,type=0,tim=10740409034
EXEC #2:c=15625,e=34772386,p=26,cr=9,cu=13,mis=0,r=0,dep=0,og=1,plh=0,tim=10740421590
ERROR #2:err=1 tim=10740421776
STAT #2 id=1 cnt=0 pid=0 pos=1 obj=0 op='LOAD TABLE CONVENTIONAL (cr=0 pr=0 pw=0 time=0 us)'
WAIT #2: nam='SQL*Net break/reset to client' ela= 10 driver id=1111838976 break?=1 p3=0 obj#=0 tim=10740422117
WAIT #2: nam='SQL*Net break/reset to client' ela= 311 driver id=1111838976 break?=0 p3=0 obj#=0 tim=10740422539
WAIT #2: nam='SQL*Net message to client' ela= 7 driver id=1111838976 #bytes=1 p3=0 obj#=0 tim=10740422628
*** 2012-06-13 11:15:34.718
WAIT #2: nam='SQL*Net message from client' ela= 11554229 driver id=1111838976 #bytes=1 p3=0 obj#=0 tim=10751976953
CLOSE #2:c=0,e=57,dep=0,type=0,tim=10751977262
=====================
上面黑体部分报错。该部分是在session 1提交后,session 2报违反唯一性错误。
下面dump结果为session2处于等待状态的时候的索引块状态,这个时候也正是读完表和索引后,进程正处于等待状态。那么这个时候的索引块状态足以说明Oracle在插入重复数据到具有unique index索引的表中时是怎么处理的,是将锁加在索引还是表上。
索引块dump出结果分析:
Dump of First Level Bitmap Block
--------------------------------
nbits : 2 nranges: 1 parent dba: 0x01429849 poffset: 0
unformatted: 4 total: 8 first useful block: 3
owning instance : 1
instance ownership changed at 06/12/2012 13:00:29
Last successful Search 06/12/2012 13:00:29
Freeness Status: nf1 0 nf2 1 nf3 0 nf4 0
Extent Map Block Offset: 4294967295
First free datablock : 3
Bitmap block lock opcode 9
Locker xid: : 0x0003.011.000003b0
Inc #: 0 Objd: 27772
HWM Flag: Not Set
Highwater:: 0x0142984c ext#: 0 blk#: 4 ext size: 8
#blocks in seg. hdr's freelists: 0
#blocks below: 1
mapblk 0x00000000 offset: 0
--------------------------------------------------------
DBA Ranges :
--------------------------------------------------------
0x01429848 Length: 8 Offset: 0
0:Metadata 1:Metadata 2:Metadata 3:25-50% free
4:unformatted 5:unformatted 6:unformatted 7:unformatted
--------------------------------------------------------
End dump data blocks tsn: 4 file#: 5 minblk 170056 maxblk 170056
从上面索引块dump出的结果看,在索引块上加了锁。
5. 测试结果分析
由以上测试过程总结:
当插入数据到有unique索引的表并且进程未提交,这时再有其他进程插入重复数据到该表时。 Oracle首先将数据写入到数据块,在维护索引叶子节点时发现已经有相同的数据在索引块中存在,则会在索引块上加锁并阻塞进程。
重复数据插入unique列时,锁加在哪?的更多相关文章
- Redis setNX 实现分布式锁(重复数据插入可用其来实现排他锁)
使用Redis的 SETNX 命令可以实现分布式锁,下文介绍其实现方法. SETNX命令简介 命令格式 SETNX key value 将 key 的值设为 value,当且仅当 key 不存在. 若 ...
- linq 获取不重复数据,重复数据 var unique = arr.GroupBy(o => o).Where(g => g.Count() == 1) .Select(g => g.ElementAt(0));
static void Main(string[] args) { int[] arr = { 1, 3, 3, 3, 3, 4, 5, 4, 5, 8, 9, 3 }; //不重复 var uniq ...
- Python将数据插入到数据库时遇到单引号插入错误的问题
这才是真正的解决方法,真不知道有些人连试都没试过就乱转载 比如你要插入一个字符串,是一个变量 如:str = "I'am a handsom boy" 由于这个字符串包含',插入数 ...
- SQL表之间复制数据、选出随机几条数据、删除重复数据、取得自增长列等操作
--表之间数据复制 SELECT* INTO yozhu FROM yo --复制一份表 SELECT* INTO yozhu1 FROM yo where 1<>1 --只复制表结构,无 ...
- kafka 如何不消费重复数据?比如扣款,我们不能重复的扣?
其实还是得结合业务来思考,我这里给几个思路: 比如你拿个数据要写库,你先根据主键查一下,如果这数据都有了,你就别插入 了,update 一下好吧. 比如你是写 Redis,那没问题了,反正每次都是 s ...
- mysql insert插入时实现如果数据表中主键重复则更新,没有重复则插入的四种方法
[CSDN下载] Powerdesigner 设计主键code不能重复等问题 [CSDN博客] Oracle中用一个序列给两个表创建主键自增功能的后果 [CSDN博客] MySQL自增主键删除后重复问 ...
- mysql总结:索引,存储引擎,大批量数据插入,事务,锁
mysql总结 索引概述: 索引是高效获取数据的数据结构 索引结构: B+Tree() Hash(不支持范围查询,精准匹配效率极高) 存储引擎: 常见存储引擎: Myisam:5.5之前默认引擎,支持 ...
- DataGridView绑定数据库,取得的数据插入到DataGridView指定列(一)
实现: 点击button1,从数据库中获得数据,指定数据库的某列数据插入到DataGridView指定列 一.双击button1进入事件代码 private void button1_Click(ob ...
- 只用css实现“每列四行,加载完一列后数据自动填充到下一列”的效果
只用css实现“每列四行,加载完一列后数据自动填充到下一列”的效果.这个题目用图表示如下: 如果将题目换成“只用css实现每行四列,加载完一行后数据自动填充到下一行”,那这个问题就简单多了,相信大家都 ...
随机推荐
- android 98 MediaPlayer+SurfaceView播放视频
package com.itheima.videoplayer; import java.io.IOException; import android.media.MediaPlayer; impor ...
- 编译openjdk源码
http://www.cnblogs.com/ACFLOOD/p/5528035.html
- Bash For Loop Examples for Your Linux Shell Scripting--ref
There are two types of bash for loops available. One using the “in” keyword with list of values, ano ...
- 谈谈Javascript线程
其实,大家都知道Javascript的语言执行环境是单线程的,浏览器无论在什么时候都有且只有一个线程在运行Javascript程序.那Ajax发送异步请求怎么解释,setTimeout/s ...
- [转]ORACLE 绑定变量用法总结
转:http://blog.csdn.net/wanghai__/article/details/4778343 在oracle 中,对于一个提交的sql语句,存在两种可选的解析过程, 一种叫做硬解析 ...
- 【转】Java web 编解码
几种常见的编码格式 为什么要编码 不知道大家有没有想过一个问题,那就是为什么要编码?我们能不能不编码?要回答这个问题必须要回到计算机是如何表示我们人类能够理解的符号的,这些符号也就是我们人类使用的语言 ...
- php 5.3+ 连接mssql
php5.3+里已经没有mssql的dll扩展了,需要使用SQL Server Driver for PHP 这里有两个版本有两个版本支持不同的php版本. 1.SQL Server Driver f ...
- java编写一个端口扫描器
好久没写java了,学的时候,也没学习网络编程这一块,无意中看到了一本书,于是小小复习一下java,写个端口扫描器,玩玩吧,网上这种小公具有的是,就是自己无聊写着玩玩. 源代码如下: 共两个类,比较简 ...
- git研究1
error:src refspec master does not match any 将本地GIT版本库PUSH到一个GITHUB上一个空的版本库时出现错误,本地版本库为空, 空目录不能提交 (只 ...
- linux下源码安装软件
在linux下的很多软件都是通过源码包方式发布的,这样做对于最终用户而言,虽然相对于二进制软件包,配置和编译起来繁琐点,但是它的可移植性却好得多,针对不同的体系结构,软件开发者往往仅需发布同一份源码包 ...