这篇文章主要介绍“怎么理解Oracle的lock和latch”,在日常操作中,相信很多人在怎么理解Oracle的lock和latch问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么理解Oracle的lock和latch”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
在开发多用户,数据库驱动的应用时,最大的难点之一是:一方面要力争最大限度的并发访问,与此同时还要确保每个用户保证用户一致性的前提下读取和修改数据。所以就出现了锁(lock)这个机制。
锁(lock)用于管理对共享资源的并发访问。举一个很形象的例子:
user1 在它的session中的一个事务获取了一个一行数据,放在本地的内存,显示给了user1;
user2在它的session中的一个事务也获取了这个数据,显示给user2;
user1 使用它的应用修改了这行数据,然后commit之后,session中的该事务已经完成
user2也修改了这行数据,commit之后,完成该项事务
这个过程知之为“更新丢失”,因为user1所做的修改将会全部丢失。所以这种情况,Oracle便有了锁这种设定,而锁也有两种策略:悲观锁(pessimistic)和乐观锁(optimistic)
悲观锁
悲观锁,顾名思义,Oracle认为你只要有会话连接,怕其他会话一定会进行数据上的修改,所以只要有session的事务牵涉到数据表,Oracle便会对其加一个行锁,防止其他用户对其修改,直到该session 中的事务提交完成。
会话便会一直在这等待,此时在user1中 commit后,user2便会执行并报出相应结果!悲观锁可以让user非常安全的对该行数据进行操作,能确保我们再进行修改之前没人对他进行其他操作。
乐观锁
乐观锁跟悲观锁是对立的,悲观锁认为可能有其他会话对我正在处理的数据进行操作,而乐观锁则认为所有会话都是友好的,不会对数据进行花里胡哨的操作。所以我们可以修改自己的数据,直到我们commit的时候才会发现我们的想法对不对。
例如我们再执行一个update语句时候,更新语句成功则说明,我们很幸运,这期间没有其他会话对其进行操作;如果最后显示的是 更新0行,这就说明另外的user修改了数据。所以需要我们考虑如果出现这种情况下下一步应该怎么处理。
这里先讨论一种使用乐观锁的方法:使用版本列的乐观锁
用简单一点的话概括就是,为原始数据做一个独一无二的标记,然后用更新数据后的标记与原始数据的标记相对比,如果相同的话,说明无人改动,则更新成功;如果不同的话则更新失败。 这种使用版本列的乐观锁难点就在于如何更新我们的‘版本列’。但是这个问题在oracle中倒是很容易解决。只需在对应的每个表上添加以number 或date/timestamp类型的列,然后通过表上的行触发器或者存储过程来维护。(触发器会在修改操作之外增加额外开销,慎用!)
那究竟是使用乐观锁还是悲观锁呢?事实上,悲观锁在处理并发时工作得很好,但是在如今的高并发的各种应用中,悲观锁要对事务始终保持连接 ,这个代价太大了,也就是我们常说的利大于弊,所以,在目前大多数应用中,多数采用的是乐观锁并发控制,并且使用版本列的乐观锁这种方法。
在Oracle中主要有三类锁,DML锁,DDL锁,内部锁和闩:我们先主要介绍一下DML锁
DML锁用于确保一次只有一个人能修改某一行;Oracle 会一种比较透明的方式添加这种锁。
TX锁
当事务发起了第一个修改时会得到一个TX锁(事务锁),该TX锁会一直拥有直到事务提交。TX锁作为一种排队机制,使得其他会话可以等待该事务完成。由于锁是事务的一个属性,所只要事务找到了数据,而数据没有被锁定,则对其锁定。如果数据被锁定了,则请求锁的会话将会等待,等待目前拥有锁的事务执行,然后得到数据。
TM锁
TM锁用于确保修改表内容时,表的结构不变;例如在我更新了表中一行数据的时候,我同时会得到这张表上的一个TM锁;防止其他用户对该表执行drop或者alter的命令。
说完了锁的工作原理以及其两种锁机制,接下来讲讲闩(latch)
闩(latch)是一种轻量级的串行设备,用于协调对共享数据结构、对象和文件的多用户访问。闩是一种锁,而锁是一种串行化的设备,所以为了更好的扩展应用,就必须寻找合适的方法减少闩(锁)的数量。
为什么说闩是种轻量级的锁,因为闩的设计只为了持有一小段时间,而不是因为他影响小被称为轻量级,事务一般会在内部以一种“愿意等待”的姿态去请求闩。如果没请求道闩,则该会话会休眠一段时间,然后再尝试这个请求操作,这里的机制是休眠不用排队;而队列锁(enqueue)则允许请求者排队者等待资源,所以请求者会出现阻塞。话题转回来,闩允许会话休眠,然后再让该会话再次请求该资源;这里就涉及到闩的特殊操作:自旋(spin):就是在不断尝试得到闩。因为上下文切换(context switching:指被踢出CPU,然后又要必须调度回到cpu中)的资源消耗很大,所以进程不能立即得到闩的话,我们会让该进程一直在cpu里不出去,一直尝试得到闩;因为闩设计的就是极短时间内的设定,所以说持有闩的会话会很快的放弃闩,让其他进程得到闩;如果一直得不到闩的话,该会话才会放弃cpu,让其他进程享用资源,自己进行休眠。
这个休眠的动作一般是多个会话同时请求同一个闩才会发生,虽然每个持有的时间很短,但是数量一多,累加起来时间就长了。
到此,关于“怎么理解Oracle的lock和latch”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!