怎么理解Oracle的lock和latch

41次阅读
没有评论

共计 2362 个字符,预计需要花费 6 分钟才能阅读完成。

这篇文章主要介绍“怎么理解 Oracle 的 lock 和 latch”,在日常操作中,相信很多人在怎么理解 Oracle 的 lock 和 latch 问题上存在疑惑,丸趣 TV 小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么理解 Oracle 的 lock 和 latch”的疑惑有所帮助!接下来,请跟着丸趣 TV 小编一起来学习吧!

在开发多用户,数据库驱动的应用时,最大的难点之一是:一方面要力争最大限度的并发访问,与此同时还要确保每个用户保证用户一致性的前提下读取和修改数据。所以就出现了锁(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”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注丸趣 TV 网站,丸趣 TV 小编会继续努力为大家带来更多实用的文章!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-07-24发表,共计2362字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)