oracle通过闩锁(latch)和锁定(lock)来实现资源的串行化。闩锁和锁定相同点是:都是用于实现保护数据的完整与准确性。不同点是:闩锁是一个低级别,轻量级的锁,获得和释放的速度非常快。而锁定则持续的时间较长,通过队列,按照先进先出的方式实现。可以这么说:闩锁是微观领域的,锁定则是宏观领域的。

那闩锁到底起的是什么作用?这么说吧,只要涉及到内存地址的读和写,都需要通过获得闩锁(latch)来实现串行化。一次只能有一个服务器进程读或者写内存地址,这样就保证了存放在该内存地址数据的准确性。

一个会话请求闩锁的时候,有可能这个闩锁正被其他会话占用。这个时候是否选择等待取决于你以什么模式请求闩锁,如果选择willing to wait(愿意等待),我们的会话就会睡眠一段时间继续请求。如果选择immediate(立即),我们的会话就会做其他的事情(比如获取另外一个相当的空闲闩),而不是等待这个闩直到可用。

由于一个闩可能有很多会话在等待其变得可用,这些等待者是否会排队呢,比如先等的排在前面?其实这个不会,这些等待者是在不断重复请求这个闩锁的,一旦这个闩锁被释放,最先请求的就会先得到。

那这些等待者是如何进行等待的呢?其实等待闩锁是一个开销比较大的事情,如果闩锁不可用,我们就得等待。在一台多cpu的机器上(如果单cpu,就没有等待闩锁这一说了),我们的会话就会自旋(spin)。

什么叫做自旋?就是我们的会话不切出cpu,会一直呆在cpu上,不断循环请求得到这个闩。因为切出cpu,醒来之后又要调入cpu非常浪费时间,而且这个闩的持有者非常有可能正在另外一个cpu上忙于处理,而且会很快释放这个闩。大多数情况,我们的会话会很快得到这个闩的。如果请求很多次之后,还是不能得到这个闩,我们的会话就会进行睡眠,让出cpu。

由此可以看出,即使有的时候我们的cpu看起来很忙,其实没干多少事情。如果你的程序写得足够糟糕,那cpu大多数的时间在不断循环请求闩锁,其实没干多少实际的工作。这就是为什么写sql语句最好用绑定变量的方法。

下面我们做一个测试:。我们会把一个编写得很好的程序和一个编写得不太好的程序进行比较,前者使用了绑定变量,而在编写得不好的程序中,每条语句使用了SQL直接量或各不相同的SQL。为此,我们使用了一个很小的Java程序,它只是登录Oracle,关掉自动提交,并通过一个循环执行25 000条不同的INSERT语句。

要评估这些程序以及它们在多用户环境中的行为,我们用Statspack来收集度量信息(什么是statspack参考我的这篇博文:http://liwenshui322.iteye.com/admin/blogs/1183027),

如下:
(1) 执行一个Statspack快照来收集系统的当前状态。
(2) 运行程序的N个副本,每个程序向其自己的数据库表中插入(INSERT),以避免所有程序都试图向一个表中插入而产生的竞争。
(3) 在最后一个程序副本执行后,紧接着取另一个快照。
然后只需打印出Statspack报告,并查看完成N个程序副本需要多长时间,使用了多少CPU时间,主要的等待事件是什么,等等。

使用绑定变量java源码:

package cn.netjava.latch; import java.sql.Connection; import java.sql.PreparedStatement; public class LatchTestMain { public static void main(String args[]) throws Exception{ Connection conn = ConnectOracle.getConn(); conn.setAutoCommit(false); String sql = "insert into latch_test1(id) values(?)"; PreparedStatement ps = conn.prepareStatement(sql); for(int i=0;i<25000;i++){ ps.setInt(1, i); ps.executeUpdate(); } conn.commit(); conn.close(); } }

不使用了绑定变量的java源码

package cn.netjava.latch; import java.sql.Connection; import java.sql.Statement; public class LatchTestMain { public static void main(String args[]) throws Exception{ Connection conn = ConnectOracle.getConn(); conn.setAutoCommit(false); Statement st = conn.createStatement(); for(int i=0;i<25000;i++){ String sql = "insert into latch_test1(id) values("+i+")"; st.execute(sql); } conn.commit(); conn.close(); } }

不使用绑定变量与使用了绑定变量Statspack报告对比

不使用绑定变量:

 使用绑定变量:

对比可以看出1S硬解析的次数不是一个数量级的。

不使用绑定变量


 
    使用绑定变量

对比可以看出cpu的时间也有很大区别。说明如果不使用绑定变量,大部分时间都会耗在硬解析这项重复没有意义的事情上面。

上面的报告都是单用户模式下(一个用户)。在实际情况当中,肯定是多用户模式了,假如我们一次跑4个程序副本看看报告是什么样子。

不使用绑定变量

使用绑定变量

发现不使用绑定变量的话,随着用户的增加,硬解析次数也增加了。而使用了绑定变量的话,硬解析次数没有什么改变。在这里是0,因为我们以前跑过一次了。

不使用绑定变量


 
 使用绑定变量


 
 对比单用户模式,不使用绑定变量的话,cpu耗时4用户是单用户的4倍多(理论上应该是4倍,至于多出来的时间,应该是耗在闩自旋上面了。)使用了绑定变量只有3倍。

以共享池为例,我们来看闩自旋。

单用户模式不使用绑定变量

4用户模式不使用绑定变量

很明显,对于shared pool 请求的次数后者是前者的4倍左右,但是Misses次数(请求闩锁失败)要高出好多,屡次请求不到而进入睡眠的也高出好多。由此可以看出,如果不使用绑定变量的话,在数以百计的用户同时访问的时候,简直是自寻死路。 同时访问的用户越多,闩自旋的概率越大,浪费cpu的时间就越多。

ORACLE 闩锁介绍相关推荐

  1. oracle中栓锁,oracle 闩锁介绍

    oracle通过闩锁(latch)和锁定(lock)来实现资源的串行化.闩锁和锁定相同点是:都是用于实现保护数据的完整与准确性.不同点是:闩锁是 一个低级别,轻量级的锁,获得和释放的速度非常快.而锁定 ...

  2. oracle 闩锁(latch)概述

        这是在网上看到的一篇文章,感觉这个知识点挺重要的,特地分享出来. Oracle数据库使用闩锁来管理内存的分配和释放.假设,某个用户进程(假设其为A)发出一条update语句,要去更新58号数据 ...

  3. 介绍了Oracle数据库锁的种类及研究

    http://www.dedecms.com/web-art/shujuku/Oracle/20061008/37324.html 介绍了Oracle数据库锁的种类及研究 来源:ZDNET 作者:佚名 ...

  4. oracle中栓锁,特定的闩锁和互斥场景

    1. Library Cache Mutex等待 库缓存是共享池的一部分,在共享池里有SQL的缓存定义.PL/SQL和JAVA类.对库缓存的修改收到library cache mutex的保护.在Or ...

  5. oracle sysobject,SQL2000数据库提示未能读取并闩锁页 sysobjects 失败数据库修复

    SQL2000数据库提示未能读取并闩锁页 sysobjects 失败数据库修复 哈尔滨海月数据恢复中心为哈尔滨某速达用户成功解决SQLServer2000数据库DBCC检测提示"未能读取并闩 ...

  6. oracle 闩情况,理解oracle锁和oracle闩(3)TX锁和TM锁

    oracle没有锁管理器和锁列表,这样可以避免行级锁维护的开销和行级锁数量不足导致的争用问题.在Oracle的每行数据上,都有一个标志位来表示该行数据是否被锁定,要查看某一行是否被锁定,必须直接找到这 ...

  7. oracle 分析锁,ORACLE锁机制分析

    Oracle 多粒度锁机制介绍 根据保护对象的不同,Oracle数据库锁可以分为以下几大类: (1) DML lock(data locks,数据锁):用于保护数据的完整性: (2) DDL lock ...

  8. SQL Serer闩锁 和 闩锁超时故障排除

    翻译自:https://mssqlwiki.com/2012/09/07/latch-timeout-and-sql-server-latch/ 在一个多线程的进程里,当一个线程在内存里更新一个数据或 ...

  9. Oracle数据库锁的种类及研究

    数据库是一个多用户使用的共享资源.当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况.若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性. 在数据库中有两 ...

最新文章

  1. [置顶]       加载事件js代码
  2. python分支结构使用if保留字吗_关于Python分支结构,以下选项中描述不正确的是...
  3. Photoshop一些人像处理技巧总结
  4. PyQt5自定义信号与槽带示例讲解
  5. 天聪公司研发成功第三代声纹识别算法
  6. JSONObject遍历
  7. pytorch可视化实例:gradcam在resnet18上的应用(快餐式代码教程)
  8. K3默认序时簿是不体现即时库存的,如果需要在序时簿将物料的即时库存数据带入,可以按照下方的步骤实现:
  9. excel 对列数据进行去重操作
  10. 班章管家分享五一假日什么理财产品会有收益?五一假日理财攻略
  11. C语言中lwr是谁的缩写,C语言中关于字符串的操作(转)
  12. ArcGIS API for JavaScript根据两个点坐标在地图上画线
  13. 我的2020推免之路:清叉、TBSI、贵系、中山、国防科大、自动化所
  14. 跨境运营培训做亚马逊广告要注意什么
  15. 吉林省松原市谷歌高清卫星地图下载
  16. 在 Flutter 中自定义画笔 Painter
  17. 电容充电时间计算公式
  18. D0、T0、S0到账模式的区别
  19. 豆瓣Top250电影爬虫
  20. osta计算机等级考试cad,Autodesk在线考试流程介绍

热门文章

  1. 微信客服对接-唯一客服系统文档中心
  2. 24届近3年安徽大学自动化考研院校分析
  3. 主R 主A 什么意思
  4. LaTeX 自定义图题:改变图片标题文字
  5. “查看更多”与“隐藏”
  6. iOS中 语音识别功能/语音转文字教程详解 韩俊强的博客
  7. 」张顺在灯影下张时 水浒传
  8. 中南大学湘雅医院简丹主任谈相控微针用于玫瑰痤疮的治疗
  9. python股票自动交易从零开始-自动交易python
  10. 路由器芯片方案、第三方固件秘密全在这里了