ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

数据库中的锁

2021-12-14 12:32:01  阅读:128  来源: 互联网

标签:事务 加锁 数据库 乐观 线程 悲观 数据


1 锁

Java锁和数据库中的锁其实是一样的,
为了避免多个事务同时操作数据库导致数据异常,一般会通过锁机制解决。
加锁是为了避免并发导致数据出现异常,来保证数据一致

image

2-共享锁

在查询语句后面增加
LOCK IN SHARE MODE
,Mysql会对查询结果中的每行都加共享锁。
SELECT ... LOCK IN SHARE MODE;

其他线程也可以读取使
别急,慢慢来。

用了共享锁的表,而且这些线程读取的是同一个版本的数据。
当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请共享锁,否则会被阻塞。

3 -排他锁

就是我们对数据进行写操作的时候,要先获得写锁,
获得写锁的事务既可以写数据也可以读数 据。

但是如果数据库已经被别人增加了排他写锁,那么后面的事务是无法在获得该数据库的任何锁的。
也就是说,如果事务T对数据A加上排他锁后,则其他事务不能再对A加任任何类型的封锁。
获准排他锁的事务既能读数 据,又能修改数据。

用法
在查询语句后面增加
FOR UPDATE
,Mysql会对查询结果中的每行都加排他锁
SELECT ... FOR UPDATE;
当没有其他线程对查询结果集中的任何一行使用排他锁时,可以成功申请排他锁,否则会被阻塞。

写操作会被默认增加排他锁,不需要显示声明
读操作需要显式声明。

拿MySql的InnoDB引擎来说,对于
insert

update

delete
等操作。会自动给涉及的数据加排他锁;

对于一般的
select
语句,InnoDB不会加任何锁

,事务可以通过以下语句给显示加共享锁或排他锁。

共享锁:

SELECT ... LOCK IN SHARE MODE;

排他锁(悲观锁):

SELECT ... FOR UPDATE;

悲观锁

悲观锁:每次去取数据,很悲观,都觉得会被别人修改,所以在拿数据的时候都会上锁。简言之,共享资源每次都只给一 个线程使用,其他线程阻塞,等第一个线程用完后再把资源转让给其他线程。synchronized和ReentranLock等都是悲观 锁思想的体现。

优点:

悲观锁利用数据库中的锁机制来实现数据变化的顺序执行,这是最有效的办法

缺点:

一个事务用悲观锁对数据加锁之后,其他事务将不能对加锁的数据进行除了查询以外的所有操作,如果该事务执行时间很 长,那么其他事务将一直等待,那势必影响我们系统的吞吐量。

乐观锁

乐观锁:每次去取数据,都很乐观,觉得不会被被人修改。因此每次都不上锁,但是在更新的时候,就会看别人有没有在 这期间去更新这个数据,如果有更新就重新获取,再进行判断,一直循环,直到拿到没有被修改过的数据。 CAS(Compare and Swap 比较并交换)就是乐观锁的一种实现方式。

乐观锁

事务在从数据库中取数据时,会将该数据的版本也取出来(v1),当事务对数据变动完毕想要将其更新到表中时,会将之前取出的 版本v1与数据中最新的版本v2相对比,如果v1=v2,那么说明在数据变动期间,没有其他事务对数据进行修改,此时,就允许 事务对表中的数据进行修改,并且修改时version会加1,以此来表明数据已被变动。

如果,v1不等于v2,那么说明数据变动期间,数据被其他事务改动了,此时不允许数据更新到表中,一般的处理办法是通知用 户让其重新操作。不同于悲观锁,乐观锁是人为控制的。

优点:

乐观锁不在数据库上加锁,任何事务都可以对数据进行操作,在更新时才进行校验,这样就避免了悲观锁造成的吞吐量 下降的劣势。

缺点:

乐观锁因为是通过我们人为实现的,它仅仅适用于我们自己业务中,如果有外来事务插入,那么就可能发生错误。

image

74-乐观锁,悲观锁场景

image

如果悲观锁和乐观锁都可以使用,那么选择就要考虑竞争的激烈程度:
当竞争激烈(出现并发冲突的概率大)时,
悲观锁更有优势,因为乐观锁在执行更新时频繁失败,需要不断重试,浪费CPU资源。

当竞争不激烈 (出现并发冲突的概率小)时,
乐观锁更有优势,
因为悲观锁会锁住代码块或数据,其他线程无法同时访问,影响并 发,
而且加锁和释放锁都需要消耗额外的资源

悲观锁:因为悲观锁会影响系统吞吐的性能,所以适合应用在写为居多的场景下。

乐观锁:因为乐观锁就是为了避免悲观锁的弊端出现的,所以适合应用在读为居多的场景下。

121-几个锁概念

  • 重量级锁
    我们要进入一个同步、线程安全的方法时,是需要先获得这个方法的锁的,
    退出这个方法时,则会释放锁。
    如果获取不到这个锁的话,意味着有别的线程在执行这个方法,
    这时我们就会马上进入阻塞的状态,等待那个持有锁的 线程释放锁,
    然后再把我们从阻塞的状态唤醒,我们再去获取这个方法的锁。
    这种获取不到锁就马上进入阻塞状态的锁,我们称之为重量级锁

  • 轻量级锁
    重量级锁之所以要加锁,是因为他们害怕自己在这个方法执行的时候,被别人偷偷进来了,
    所以只能加锁,防止其他线程进来。
    这就相当于,每次离开自己的房间,都要锁上门,人回来了再把锁解开。
    这实在是太麻烦了,如果根本就没有线程来和他们竞争锁,
    那他们不是白白上锁了?要知道,加锁这个过程是需要操作 系统这个大佬来帮忙的,是很消耗时间的,。
    为了解决这种动不动就加锁带来的开销,轻量级锁出现了。

轻量级锁认为,当你在方法里面执行的时候,

其实是很少刚好有人也来执行这个方法的,
所以,当我们进入一个方法的 时候根本就不用加锁,
我们只需要做一个标记就可以了,也就是说,
我们可以用一个变量来记录此时该方法是否有人在 执行。
也就是说,如果这个方法没人在执行,当我们进入这个方法的时候,采用CAS机制,
把这个方法的状态标记为已 经有人在执行,
退出这个方法时,在把这个状态改为了没有人在执行了。

行锁,表锁

image

标签:事务,加锁,数据库,乐观,线程,悲观,数据
来源: https://www.cnblogs.com/hellosiyu/p/15687313.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有