重复数据插入unique列时,锁加在哪?
2013-08-05 11:21
155 查看
1.测试目的
当插入重复数据到有unique索引的表中时,采用何种加锁机制。
2.测试思路
利用10046确定是什么操作导致加锁阻塞了进程;
dump锁定前最近一次操作的块结构来分析加锁机制。
3.测试环境
SQL>select*fromv$versionwhererownum=1;
BANNER
-----------------------------------------------------------------
OracleDatabase11gEnterpriseEditionRelease11.2.0.1.0-Production
4.测试过程
表test2及其索引idx_test2_id对应的object_id。
SQL>selectobject_id,object_namefromdba_objectswhereobject_namein('TEST2','IDX_TEST2_ID');
OBJECT_IDOBJECT_NAME
-------------------------
27667TEST2
27668IDX_TEST2_ID
--session1
SQL>insertintotest2values(1,'a');
已创建1行。
此处不提交。
--session2
SQL>altersystemflushbuffer_cache;
系统已更改。
SQL>altersessionsetevents‘10046tracenamecontextforever,level8’;
SQL>insertintotest2values(1,'a');
此处一直处于等待状态。
然后将session1提交,这时session2报错。
下面dump片断是在sesson2处于等待状态时的10046跟踪结果:
=====================
PARSINGINCURSOR#2len=31dep=0uid=34oct=2lid=34tim=10705648912hv=4047255222ad='277dc964'sqlid='9u2g41msmsdpq'
insertintotest2values(1,'a')
ENDOFSTMT
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='dbfilesequentialread'ela=22644file#=5block#=170050blocks=1obj#=27667tim=10705671989
WAIT#2:nam='dbfilesequentialread'ela=10704file#=5block#=170049blocks=1obj#=27667tim=10705682866
WAIT#2:nam='dbfilesequentialread'ela=299file#=5block#=170048blocks=1obj#=27667tim=10705683300
WAIT#2:nam='dbfilescatteredread'ela=25431file#=5block#=170051blocks=5obj#=27667tim=10705708852
WAIT#2:nam='dbfilesequentialread'ela=13716file#=3block#=256blocks=1obj#=0tim=10705722841
WAIT#2:nam='dbfilesequentialread'ela=15175file#=3block#=35109blocks=1obj#=0tim=10705738184
WAIT#2:nam='dbfilescatteredread'ela=22759file#=5block#=170056blocks=8obj#=27668tim=10705775416
WAIT#2:nam='dbfilesequentialread'ela=14768file#=3block#=160blocks=1obj#=0tim=10705790482
***2012-06-1311:15:22.984
WAIT#2:nam='enq:TX-rowlockcontention'ela=34452785name|mode=1415053316usn<<16|slot=196626sequence=906obj#=0tim=10740253456
WAIT#2:nam='latch:cachebufferschains'ela=44613address=783740924number=150tries=0obj#=0tim=10740298330
=====================
上面黑体部分,27667是表test2,27668是索引idx_test2_id,这个地方报等待事件“enq:TX-rowlockcontention”了。
下面这部分片断为session1提交后,session2报违反唯一性错误时的10046片断。
=====================
PARSINGINCURSOR#1len=84dep=1uid=0oct=3lid=0tim=10740356283hv=2686874206ad='29cece34'sqlid='2skwhauh2cwky'
selecto.name,u.namefromobj$o,user$uwhereo.obj#=:1ando.owner#=u.user#
ENDOFSTMT
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='dbfilesequentialread'ela=8833file#=1block#=337blocks=1obj#=36tim=10740368472
WAIT#1:nam='dbfilesequentialread'ela=18496file#=1block#=36489blocks=1obj#=36tim=10740387126
WAIT#1:nam='dbfilesequentialread'ela=13908file#=1block#=35771blocks=1obj#=18tim=10740401184
WAIT#1:nam='dbfilesequentialread'ela=6505file#=1block#=217blocks=1obj#=11tim=10740407986
WAIT#1:nam='dbfilesequentialread'ela=343file#=1block#=210blocks=1obj#=22tim=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#1id=1cnt=1pid=0pos=1obj=0op='NESTEDLOOPS(cr=5pr=5pw=0time=0uscost=4size=45card=1)'
STAT#1id=2cnt=1pid=1pos=1obj=18op='TABLEACCESSBYINDEXROWIDOBJ$(cr=3pr=3pw=0time=0uscost=3size=27card=1)'
STAT#1id=3cnt=1pid=2pos=1obj=36op='INDEXRANGESCANI_OBJ1(cr=2pr=2pw=0time=0uscost=2size=0card=1)'
STAT#1id=4cnt=1pid=1pos=2obj=22op='TABLEACCESSCLUSTERUSER$(cr=2pr=2pw=0time=0uscost=1size=18card=1)'
STAT#1id=5cnt=1pid=4pos=1obj=11op='INDEXUNIQUESCANI_USER#(cr=1pr=1pw=0time=0uscost=0size=0card=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=1tim=10740421776
STAT#2id=1cnt=0pid=0pos=1obj=0op='LOADTABLECONVENTIONAL(cr=0pr=0pw=0time=0us)'
WAIT#2:nam='SQL*Netbreak/resettoclient'ela=10driverid=1111838976break?=1p3=0obj#=0tim=10740422117
WAIT#2:nam='SQL*Netbreak/resettoclient'ela=311driverid=1111838976break?=0p3=0obj#=0tim=10740422539
WAIT#2:nam='SQL*Netmessagetoclient'ela=7driverid=1111838976#bytes=1p3=0obj#=0tim=10740422628
***2012-06-1311:15:34.718
WAIT#2:nam='SQL*Netmessagefromclient'ela=11554229driverid=1111838976#bytes=1p3=0obj#=0tim=10751976953
CLOSE#2:c=0,e=57,dep=0,type=0,tim=10751977262
=====================
上面黑体部分报错。该部分是在session1提交后,session2报违反唯一性错误。
下面dump结果为session2处于等待状态的时候的索引块状态,这个时候也正是读完表和索引后,进程正处于等待状态。那么这个时候的索引块状态足以说明Oracle在插入重复数据到具有uniqueindex索引的表中时是怎么处理的,是将锁加在索引还是表上。
索引块dump出结果分析:
DumpofFirstLevelBitmapBlock
--------------------------------
nbits:2nranges:1parentdba:0x01429849poffset:0
unformatted:4total:8firstusefulblock:3
owninginstance:1
instanceownershipchangedat06/12/201213:00:29
LastsuccessfulSearch06/12/201213:00:29
FreenessStatus:nf10nf21nf30nf40
ExtentMapBlockOffset:4294967295
Firstfreedatablock:3
Bitmapblocklockopcode9
Lockerxid::0x0003.011.000003b0
Inc#:0Objd:27772
HWMFlag:NotSet
Highwater::0x0142984cext#:0blk#:4extsize:8
#blocksinseg.hdr'sfreelists:0
#blocksbelow:1
mapblk0x00000000offset:0
--------------------------------------------------------
DBARanges:
--------------------------------------------------------
0x01429848Length:8Offset:0
0:Metadata1:Metadata2:Metadata3:25-50%free
4:unformatted5:unformatted6:unformatted7:unformatted
--------------------------------------------------------
Enddumpdatablockstsn:4file#:5minblk170056maxblk170056
从上面索引块dump出的结果看,在索引块上加了锁。
5.测试结果分析
由以上测试过程总结:
当插入数据到有unique索引的表并且进程未提交,这时再有其他进程插入重复数据到该表时。Oracle首先将数据写入到数据块,在维护索引叶子节点时发现已经有相同的数据在索引块中存在,则会在索引块上加锁并阻塞进程。
相关文章推荐
- MySQL使用UNIQUE实现数据不重复插入
- mysql 使用 insert ignore into和unique实现不插入重复数据功能
- mysql 插入数据 重复行处理
- 删除重复记录,保留数据库中最新插入的数据(或最早插入的数据)
- 插入及查询不重复数据的几种情况
- mysql insert插入时实现如果数据表中主键重复则更新,没有重复则插入的四种方法
- Jquery往网页插入数据遇到数据出现重复的问题
- 【转】MySQL中unique列上插入重复值的解决方法
- oracle sql 判断字段非空,数据不重复,插入多跳数据
- oracle 批量插入时,如何去除重复数据
- _mysql_exceptions.IntegrityError: (1062, "Duplicate entry, Python操作MySQL数据库,插入重复数据
- MySQL防止重复插入唯一限制的数据 4种方法
- 使用SQLiteStatement向SQLite数据库批量插入时数据重复问题
- 多表联合查询后去重复数据后重新插入第一张表解决办法
- jsp或struts如何避免Form重复提交,不然数据中的插入的纪录有重复的!
- 要求从表A查数据插入到表B中,并且要求如果表A中已存在的数据,就不要重复插入
- greendao插入数据UNIQUE constraint failed: PURCHASE_ORDER_TABLE._id (code 1555)
- 关于数据库层面上锁,解决程序并发插入多条重复数据
- ORACLE 利用触发器避免数据重复插入
- 在Sql2005中,向表中插入数据时遇到uniqueidentifier列,如何插入数据?