前面我介绍了itl引发的阻塞与死锁,这里有必要再介绍一下位图索引引发的阻塞与死锁,因为这个也是不同于普通死锁的一种死锁方式,在有位图索引存在的表上面,其实很容易就引发阻塞与死锁。这个阻塞不是发生在表上面,而是发生在索引上。因为位图索引锁定的范围远远比普通的b-tree索引锁定的范围大。

假定,一个表,上面有标志字段(flags),分别是(0、1),而我们在这个flag字段上创建了一个位图索引,那么,现在我们执行如下的语句:

Piner@10gR2>update test set flags = 1 where id = 1;

假定id=1的的值原来是0,现在要更新成1,那么,这个语句在位图索引中,将锁住id=1那个记录所在的整个索引块中的flag=0与1的值,如果这个索引块中有很多记录,这个阻塞将是很严重的。另外注意,如果操作的dml不涉及到索引,则是不会被阻塞的。所以,在oltp环境中,如果一个表更新比较频繁,千万不要使用位图索引,如果数据仓库环境中,使用了位图索引,也最好在加载数据的时候将其删除,等数据加载完成以后重新创建。

我们看一个具体的例子

Piner@10gR2>select * from test;

ID FLAG

---------- ----------

1 1

2 1

3 1

4 1

5 1

6 0

7 0

8 0

9 0

10 0

10 rows selected.

我们在上面创建一个位图索引

Piner@10gR2>create bitmap index ind_test on test(flag);

Index created.

然后更新其中的一条记录,仅仅是一条记录

Piner@10gR2>update test set flag = 0 where id=1;

1 row updated.

这个时候,其实整个位图都被锁定了(因为这些记录都在一个索引块中),我们看如下的例子,在另外的会话中,执行如下的语句可以发现:

Piner@10gR2>update test set flag = flag where id=6;

1 row updated.

Piner@10gR2>update test set flag = 1 where id=6; --blocked

可以发现第二个语句被阻塞

其实也就是说,如果不涉及到更新索引(因为第一次中,修改id=6的记录,flag值没有发生变化),那么就不会有阻塞的。当然,如果不是更新flag字段,而是其它字段,也不会有阻塞的,一旦涉及到修改flag的值,阻塞就发生了。

以上是是把0更新成1阻塞,那么把1更新成0同样阻塞

Piner@10gR2>update test set flag = flag where id=2;

1 row updated.

Piner@10gR2>update test set flag = 0 where id=2; --blocked

同样被阻塞

我们看看这个时候的等待原因,可以发现等待在TX锁上面

select EVENT from v$session_wait where sid=153 EVENT ----------------------------- enq: TX - row lock contention

理解了阻塞的原因,那么我们应当就很好理解位图死锁的原因了,数据行死锁差不多,2个进程互相锁住了资源,不同的是,行死锁抢的是同一样的数据,如同一行数据,位图索引死锁抢的是位图值,可以是不同的行。

接上面的表数据,我们模拟一个死锁,在会话1中执行如下命令

会话1

Piner@10gR2>update test set flag = 2 where id=1;

1 row updated.

以上命令一旦发出,位图索引中锁住了所有flag=1(原值)以及flag=2(新值)的记录。

在会话2

Piner@10gR2>update test set flag = 3 where id=6;

1 row updated.

这个命令锁住了所有flag=0(原值)以及flag=3(新值)的记录。

再回会话1,我们更新id=7的记录,注意,以上的操作记录都不相同。

Piner@10gR2>update test set flag = 2 where id=7; --blocked

结果是阻塞了,会话1等待会话2释放位图索引的锁定资源。

那么,我们在会话2中,再更新一条记录

Piner@10gR2>update test set flag = 3 where id=2; --blocked

虽然该记录与以上任何记录都不一样,也被阻塞了,等待会话1释放资源,到这里,死锁就形成了,马上可以看到,报了一个错在会话1上:

Piner@10gR2>update test set flag = 2 where id=7;

update test set flag = 2 where id=7

*

ERROR at line 1:

ORA-00060: deadlock detected while waiting for resource

我们看跟踪文件,发现这里锁定的是索引,因为object_id=13009的对象就是是位图索引

Deadlock graph:

———Blocker(s)——– ———Waiter(s)———

Resource Name process session holds waits process session holds waits

TX-00050027-00001599 16 148 X 19 160 S

TX-00070014-00001579 19 160 X 16 148 S

session 148: DID 0001-0010-00000032 session 160: DID 0001-0013-00000004

session 160: DID 0001-0013-00000004 session 148: DID 0001-0010-00000032

Rows waited on:

Session 160: obj - rowid = 000032D1 - AAADLRAAAAAAAAAAAA

(dictionary objn - 13009, file - 0, block - 0, slot - 0)

Session 148: obj - rowid = 000032D1 - AAADLRAAAAAAAAAAAA

(dictionary objn - 13009, file - 0, block - 0, slot - 0)

第2楼 logzgh 于2007-05-23 16:21:55 Says:

“假定id=1的的值原来是0,现在要更新成1,那么,这个语句在位图索引中,锁住所有的flag为0以及flag为1的数据,这个是比较恐怖的。更新一行数据相当于锁定了整个索引”

你这里的说法不太正确。

事实上是锁定了id=1那条记录所在的索引块上所包含的所有记录。对大表来讲,一个索引块并不会包含所有的记录,所以不是整个索引。

第3楼 piner 于2007-05-23 19:33:04 Says:

“假定id=1的的值原来是0,现在要更新成1,那么,这个语句在位图索引中,锁住所有的flag为0以及flag为1的数据,这个是比较恐怖的。更新一行数据相当于锁定了整个索引”

你这里的说法不太正确。事实上是锁定了id=1那条记录所在的索引块上所包含的所有记录。对大表来讲,一个索引块并不会包含所有的记录,所以不是整个索引。

谢谢指正。。。这里我我有时间再实验一下。

第4楼 piner 于2007-05-23 20:16:03 Says:

现在发现,你的说法也不正确,你说锁住id=1的那个索引块,其实,我这里这么少的记录,应当就是一个索引块。

但是,下面的实验可以发现,set flag=2与flag=3是互相不等待的,也就是没有锁等待,按照你的说法,除非只是锁定了这个记录所在的索引块的flag = 新值 与 原值 的所有记录。

现在,我先这么改了,是否正确,我还要验证。

第5楼 piner 于2007-05-23 20:55:44 Says:

具体位图索引的内部,可以参考

http://www.itpub.net/showthread.php?threadid=743939 其实,锁定范围也可能不仅仅是一个索引块,9i与10g的变化也是比较大的,我们现在只要知道,锁定的范围比较大,不适合频繁修改的oltp即可。

oracle 位图索引 死锁,Oracle位图索引引发的阻塞与死锁相关推荐

  1. Oracle创建索引bitmap,Oracle编程高手箴言:位图索引(Bitmap Index)的故事

    Oracle编程高手箴言:位图索引(Bitmap Index)的故事 您如果熟悉Oracle数据库,我想您对Thomas Kyte的大名一定不会陌生.Tomas主持的asktom.oracle.com ...

  2. oracle位图索引和普通索引区别,【索引】Bitmap位图索引与普通的B-Tree索引锁的比较...

    通过以下实验,来验证Bitmap位图索引较之普通的B-Tree索引锁的"高昂代价".位图索引会带来"位图段级锁",实际使用过程一定要充分了解不同索引带来的锁代价 ...

  3. oracle索引图解,oracle 位图索引详解

    一.什么是位图索引 我们目前大量使用的索引一般主要是B*Tree索引,在索引结构中存储着键值和键值的RowID,并且是一一对应的. 而位图索引主要针对大量相同值的列而创建(例如:类别,操作员,部门ID ...

  4. oracle位图索引和普通索引区别,Oracle学习之位图索引

    Oracle学习之位图索引 时间:2017-07-29 来源: 位图索引的原理 位图索引的优势 1.快速统计条数 由于位图索引只存储0和1的指,因此它的空间占用很小,向count(*)之类的操作用位图 ...

  5. Oracle索引梳理系列(四)- Oracle索引种类之位图索引

    版权声明:本文发布于http://www.cnblogs.com/yumiko/,版权由Yumiko_sunny所有,欢迎转载.转载时,请在文章明显位置注明原文链接.若在未经作者同意的情况下,将本文内 ...

  6. oracle dump enq hw,经典故障分析 - ASSM引发的索引争用与 enq HW -contentio

    作者介绍: 孙加鹏 云和恩墨技术顾问 六年Oracle技术顾问经验,所服务的行业包括电信运营商.金融业.制造业等. 擅长Oracle的故障诊断.高可用架构.升级迁移等.目前主要服务于上海金融类客户. ...

  7. oracle 执行删除索引报错,Oracle分区表删除分区引发错误ORA-01502: 索引或这类索引的分区处于不可用状态...

    (一)问题: 最近在做Oracle数据清理,在对分区表进行数据清理时,采用的方法是drop partition,删除的过程中,没有遇到任何问题,大概过了10分钟,开发人员反馈部分分区表上的业务失败.具 ...

  8. 【索引分类】位图索引

    位图索引 位图索引非常适合于决策支持系统(Decision Support System,DSS)和数据仓库,它们不应该用于通过事务处理应用程序访问的表.它们可以使用较少到中等基数(不同值的数量)的列 ...

  9. 索引名 oracle,ORACLE 索引名称矫情

    oracle 索引英文名称很多,翻译过来的话也很多中文名称,不过总得来说词不达意.也就是说讲中文的时候,对方无法理解你说的是啥意思,啥情况,啥原理. 比如前缀,非前缀.本地和全局,普通和分区.B树和位 ...

最新文章

  1. python opencv 归一化
  2. 刷道谷歌泄漏的面试题:面试官想从中考察你什么?
  3. 【Python Turtle合集】”外面的花已经开得很像样了, 我看到风拥作一团, 前来庆贺“(春天来啦~)
  4. 服务器运维一般的故障率,服务器平均故障率
  5. 软考网络工程师笔记-综合知识1
  6. 利用计算机解决鸡兔同笼问题,利用极限思想解决复杂鸡兔同笼问题
  7. 使用allegro画PCB的基本流程:
  8. 3dmax测试软件自动关闭,3dmax软件会自动关闭解决方案
  9. MySQL实战系列3:视图、存储过程、函数、索引全解析
  10. 机器学习-算法原理与编程实践(郑捷.著)-阅读笔记
  11. 给IDEA换个酷炫的主题,这个有点哇塞啊!
  12. fatal Couldn‘t find remote ref master
  13. Tita绩效宝:在360度评估中要问的10个最佳问题
  14. 電腦機房空調氣流設計與節能
  15. python 键盘输入矩阵
  16. weixuan -小老弟做鸭(函数)
  17. 蓝桥杯嵌入式(一)学习准备
  18. $timeformat $time
  19. 华为HCIA-datacom 学习笔记11——AAA原理与配置
  20. IK分词器的安装和扩展词典的使用

热门文章

  1. CountDownTimer用法详解
  2. CountDownTimer源码解析
  3. Vmware 8导致apache2无法启动的情况
  4. verilog产生随机数序列_总结verilog产生随机数的$random和seed
  5. 无锡格瑞驰车业 ipad做汽车导航
  6. MATLAB的函数句柄
  7. 百度大脑黑白图像上色-老照片的春天
  8. 数据库存储图片 Blod格式2(下载)
  9. MPEG-PCC基于几何点云压缩(G-PCC codec description v12)学习笔记
  10. 锐捷(五)vlan高级之supervlan