程序员过关斩将--数据库的乐观锁和悲观锁并非真实的锁

640?wx_fmt=gif

菜菜哥,告诉你一个消息

640
640?wx_fmt=jpeg

你有男票啦?

640
640?wx_fmt=jpeg

非也非也,我昨天出去偷偷面试,结果又挂了

640
640?wx_fmt=jpeg

哦,看来公司是真的不想让你走呀

640
640?wx_fmt=jpeg

面试官让我说一下乐观锁和悲观锁,我没回答上来,回来之后我查了,数据库没有这两种锁呀

640
640?wx_fmt=jpeg

了解这两种锁之前,我觉得你需要先了解一下数据库的锁机制

640
640?wx_fmt=jpeg
640?wx_fmt=gif

开局

640

我们平时编写程序的时候,有很多情况下需要考虑线程安全问题,一个全局的变量如果有可能会被多个同时执行的线程去修改,那么对于这个变量的修改就需要有一种机制去保证值的正确性和一致性,这种机制普遍的做法就是加锁。其实也很好理解,和现实中一样,多个人同时修改一个东西,必须有一种机制来把多个人进行排队。计算机的世界中也是如此,多个线程乃至多个进程同时修改一个变量,必须要对这些线程或者进程进行排队。数据库的世界亦是如此,多个请求同时修改同一条数据记录,数据库必须需要一种机制去把多个请求来顺序化,或者理解为同一条数据记录同一时间只能被一个请求修改。

锁是数据库中最为重要的机制之一,无论平时写的select语句,还是update语句其实在数据库层面都和锁息息相关。如果没有锁机制,操作数据的时候可能会发生以下情况:

1. 更新丢失:多个用户同时对一个数据资源进行更新,必定会产生被覆盖的数据,造成数据读写异常。

2. 不可重复读:如果一个用户在一个事务中多次读取一条数据,而另外一个用户则同时更新啦这条数据,造成第一个用户多次读取数据不一致。

3. 脏读:第一个事务读取第二个事务正在更新的数据表,如果第二个事务还没有更新完成,那么第一个事务读取的数据将是一半为更新过的,一半还没更新过的数据,这样的数据毫无意义。

4. 幻读:第一个事务读取一个结果集后,第二个事务,对这个结果集经行增删操作,然而第一个事务中再次对这个结果集进行查询时,数据发现丢失或新增。

数据管理角度

640?wx_fmt=gif

在数据库管理的角度或者数据行的角度来说,数据库锁可以分为共享锁和排它锁,这是面试过程中经常被提及的两种类型。本质其实很简单,站在数据的角度来看,如果数据当前正在被访问,下一个访问的请求该如何处理?和计算机二进制一样,无非就是允许被访问和不允许访问两种状态。

共享锁

640

共享所被称为读锁或者S锁,就像以上所述,共享锁在新请求访问一个数据的时候,如果是读请求则允许,如果是写(删改)请求,则不允许。由于共享锁允许其他的读操作,所以通常情况下共享锁只应用于select操作,如果一个update或者delete操作应用共享锁会发生很严重的数据不一致情况。

独占锁

640

独占锁也被称为排它锁或者X锁,相对于共享锁,独占锁采用的态度比较坚决,一旦数据被独占锁锁定,其他任何请求(包括读操作)都必须等待独占锁的释放才可以继续,只有当前锁定数据的请求才可以修改读取数据。

更新锁

640

当数据库准备更新数据时,它首先对数据对象作更新锁锁定,这样数据将不能被修改,但可以读取。等到确定要进行更新数据操作时,他会自动将更新锁换为独占锁,当对象上有其他锁存在时,无法对其加更新锁。

意向锁

640

简单来说就是给更大一级别的空间示意里面是否已经上过锁。例如表级放置了意向锁,就表示事务要对表的页或行上使用共享锁。在表的某一行上上放置意向锁,可以防止其它事务获取其它不兼容的的锁。意向锁可以提高性能,因为数据引擎不需要检测资源的每一列每一行,就能判断是否可以获取到该资源的兼容锁。意向锁包括三种类型:意向共享锁(IS),意向排他锁(IX),意向排他共享锁(SIX)。

640?wx_fmt=gif

实际应用中,站在数据的角度可以看出,数据只允许同时进行一个写操作

颗粒度角度

640

锁用来对数据进行锁定,我们可以从锁定对象的粒度大小来对锁进行划分,分别为行锁、页锁和表锁。

1. 行级锁是数据库中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突。其加锁粒度最小,但加锁的开销也最大。特点:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

2. 表级锁是数据库中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少。特点:开销小,加锁快;不会出现死锁;锁定粒度大,发出锁冲突的概率最高,并发度最低。

3. 页级锁是数据库中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突少,但速度慢。所以取了折衷的页级,一次锁定相邻的一组记录。特点:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般

不同数据库支持的锁力度不同,甚至同一种数据库不同的引擎支持的锁力度都不同,如下表所示(来源于网络)

640?wx_fmt=png

640?wx_fmt=gif

这里要强调一点,无论什么数据库对数据加锁,都需要资源的消耗,因此锁的数量其实是有上限的,当锁数量到达这个上限会自动进行锁力度的升级,用更大力度的锁来代替多个小力度的锁。

乐观锁和悲观锁

乐观锁

640

乐观锁认为一般情况下数据不会造成冲突,所以在数据进行提交更新时才会对数据的冲突与否进行检测。如果没有冲突那就OK;如果出现冲突了,则返回错误信息并让用户决定如何去做。类似于 SVN、GIt这些版本管理系统,当修改了某个文件需要提交的时候,它会检查文件的当前版本是否与服务器上的一致,如果一致那就可以直接提交,如果不一致,那就必须先更新服务器上的最新代码然后再提交(也就是先将这个文件的版本更新成和服务器一样的版本)

乐观锁是一种程序的设计思想,通过一个标识的对比来决定数据是否可以操作,现在普遍的做法是给数据加一个版本号或者时间戳的方式来实现乐观锁操作过程:

在表中设计一个版本字段 version,第一次读的时候,会获取 version 字段的取值。然后对数据进行更新或删除操作时,会执行UPDATE ... SET version=version+1 WHERE version=version。此时如果已经有事务对这条数据进行了更改,修改就不会成功。

悲观锁

640

每次获取数据的时候,都会担心数据被修改,所以每次获取数据的时候都会进行加锁,确保在自己使用的过程中数据不会被别人修改,使用完成后进行数据解锁。由于数据进行加锁,期间对该数据进行读写的其他线程都会进行等待。

总结

640?wx_fmt=gif

无论是乐观锁和悲观锁,并非是数据库自身持有的锁类型(虽然悲观锁形式上很像独占锁),而是程序设计的一种思想,是一种类似数据库锁机制保护数据一致性的策略。

640

1. 悲观锁比较适合写入操作比较频繁的场景,如果出现大量的读取操作,每次读取的时候都会进行加锁,这样会增加大量的锁的开销,降低了系统的吞吐量。

2. 乐观锁比较适合读取操作比较频繁的场景,如果出现大量的写入操作,数据发生冲突的可能性就会增大,为了保证数据的一致性,应用层需要不断的重新获取数据,这样会增加大量的查询操作,降低了系统的吞吐量。

写在最后

640?wx_fmt=gif

程序编写过程中,操作数据无论采用哪个类型的锁,都需要注意死锁的发生,一个死锁有可能对整个应用是致命的。死锁的本质是对资源竞争的一种失败表现,所以sql语句的编写过程中对于多表的操作最好采用一致的顺序来进行,另外一个种极端的方式可以一次性锁定所有资源,而非逐步来锁资源。

640?wx_fmt=gif

640?wx_fmt=gif
END
640?wx_fmt=gif
640?wx_fmt=gif

640?wx_fmt=jpeg


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/313273.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

solverstate的使用

http://blog.csdn.net/wang4959520/article/details/51831637 我们在使用caffe训练过程中会生成.caffemodel和.solverstate文件,一个是模型文件,一个是中间状态文件(生成多少个取决于你自己设定的snapshot)。当训练过程中断&#…

IT从业者的迷思与求解之道——座谈会实录摘选

本次座谈会于上周六开始,由于网络原因,很多国内的小伙伴们没有能够连进去,挺遗憾的。所以我整理了本次座谈会的部分内容,希望能对大家有所帮助。洞察力主持人:大家好我们来自开源社群,今天举行在线it社区的…

准确率、召回率、F1、mAP、ROC、AUC

https://yongyuan-workbench.rhcloud.com/%E4%BF%A1%E6%81%AF%E6%A3%80%E7%B4%A2ir%E7%9A%84%E8%AF%84%E4%BB%B7%E6%8C%87%E6%A0%87%E4%BB%8B%E7%BB%8D-%E5%87%86%E7%A1%AE%E7%8E%87%E3%80%81%E5%8F%AC%E5%9B%9E%E7%8E%87%E3%80%81f1%E3%80%81map%E3%80%81r/准确率、召回率、F1…

从零开始实现ASP.NET Core MVC的插件式开发(六) - 如何加载插件引用

标题:从零开始实现ASP.NET Core MVC的插件式开发(六) - 如何加载插件引用。 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p/11717254.html源代码:https://github.com/lamondlu/DynamicPlugins前景回顾•••••简介在前…

小波变换基础

http://blog.csdn.net/GarfieldEr007/article/details/50151845 第十二章 小波变换 目录 1 引言 2 连续小波变换 3 二进小波变换 3.1 Haar变换 4 离散小波变换 4.1 多分辨率分析 4.2 快速小波变换算法 4.3 离散小波变换的…

.Net Core3.0使用gRPC

gRPC是什么gRPC是可以在任何环境中运行的现代开源高性能RPC框架。它可以通过可插拔的支持来有效地连接数据中心内和跨数据中心的服务,以实现负载平衡,跟踪,运行状况检查和身份验证。它也适用于分布式计算的最后一英里,以将设备&am…

单链表逆向

转自:http://blog.csdn.net/heyabo/article/details/7610732 对于单链表的逆置有两种方法可以实现: (1)利用辅助指针 基本思想:在遍历结点过程中,设置辅助指针,用于记录先前遍历的结点。这样依次…

中国.NET开发者峰会特别活动-基于k8s的微服务和CI/CD动手实践报名

2019.11.9 的中国.NET开发者峰会将在上海举办,到目前为止,大会的主题基本确定,这两天就会和大家会面,很多社区的同学基于对社区的信任在我们议题没有确定的情况下已经购票超过了300张,而且分享的主题都来自于社区&…

高斯混合模型学习

转自:http://blog.csdn.net/jojozhangju/article/details/19182013 1.高斯混合模型概述 高斯密度函数估计是一种参数化模型。高斯混合模型(Gaussian Mixture Model, GMM)是单一高斯概率密度函数的延伸,GMM能够平滑地近似任意形状的…

[工具]OFFICE插件管理工具-帮助更好地管理及使用电脑安装过的OFFICE插件

在OFFICE软件的世界中,除了由微软提供的OFFICE软件功能外,还有大量的功能由第三方开发者完成,市面上也存在大量的OFFICE插件供用户选择。使用场景有些插件仅在某个特定场景下才会使用,日常办公过程中,无需开启&#xf…

随机梯度下降的实现细节

http://www.miaoerduo.com/deep-learning/%E5%9F%BA%E4%BA%8Ecaffe%E7%9A%84deepid2%E5%AE%9E%E7%8E%B0%EF%BC%88%E4%B8%8A%EF%BC%89.html 最近看了一篇文章,详细说明了随机梯度下降中随机是在create_imagenet.sh中shuffle实现的。 相关资源: DeepID&am…

那位标榜技术驱动的开发者去哪了?

作者:邹溪源,长沙资深互联网从业者,架构师社区合伙人!一他是一位曾经标榜技术驱动世界的开发者,在他年轻的时候,一段独特的经历,让他对技术充满了兴趣,并在技术这条道路上走了很远很…

图像PCA方法

http://blog.csdn.net/lifeng_math/article/details/50014073 http://blog.csdn.net/lifeng_math/article/details/49993763#旋转不变的-lbp 引言 PCA是Principal Component Analysis的缩写,也就是主成分分析。也是用于降维常用的一中方法。PCA 主要用于数据降维&a…

.NET实时2D渲染入门·动态时钟

前言说来这是个我和我老婆的爱情故事。从小以来“坦克大战”、“魂斗罗”等游戏总令我魂牵梦绕。这些游戏的基础就是 2D实时渲染,以前没意识,直到后来找到了 Direct2D。我的 2D实时渲染入门,是从这个 动态时钟开始的。本文将使用我写的“准游…

ASP.NET Core在 .NET Core 3.1 Preview 1中的更新

.NET Core 3.1 Preview 1现在可用。此版本主要侧重于错误修复,但同时也包含一些新功能。对Razor components的部分类支持将参数传递给顶级组件在HttpSysServer中支持共享队列在SameSite cookies的重大更改除了.NET Core 3.1 Preview版本发布之外,我们还发…

小波变换学习(1)

转自:https://www.zhihu.com/question/22864189/answer/40772083从傅里叶变换到小波变换,并不是一个完全抽象的东西,可以讲得很形象。小波变换有着明确的物理意义,如果我们从它的提出时所面对的问题看起,可以整理出非常…

.NET Core 3.0 新 JSON API - JsonDocument

JsonDocument类 JsonDocument是基于Utf8JsonReader 构建的。JsonDocument 可分析 JSON 数据并生成只读文档对象模型 (DOM),可对模型进行查询,以支持随机访问和枚举。使用 JsonDocument 分析常规 JSON 有效负载并访问其所有成员比使用 Json.NET 快 2-3 倍…

微软推出 Microsoft.Data.SqlClient,替代 System.Data.SqlClient

背景在 .NET 创建之初,System.Data 框架是一个重要的组件。它为创建 .NET 数据库驱动程序提供了一种方式,类似 Visual Basic 的 ActiveX Data Objects。虽然 API 不一样,但重用了它的名称,所以才有了 ADO .NET 这个绰号。ADO 和 A…

C++ 从文件夹中读取文件

OpenCV从文件夹中读取内含文件方法 参考&#xff1a;http://www.2cto.com/kf/201407/316515.html http://www.it610.com/article/5126146.htm http://blog.csdn.net/adong76/article/details/39432467 windows平台代码&#xff1a; [cpp] view plaincopy #include <io.h&…

你必须知道的容器监控 (1) Docker自带子命令与Weave Scope

本篇已加入《》&#xff0c;可以点击查看更多容器化技术相关系列文章。本篇会介绍几个目前比较常用且流行的容器监控工具&#xff0c;首先我们来看看Docker自带的几个监控子命令&#xff1a;ps、top以及stats&#xff0c;然后是一个功能更强的开源监控工具Weave Scope。# 实验环…