锁定义及其作用-数据库锁解析-数据库中的锁定义 (锁定的定义)

教程大全 2025-07-18 22:53:25 浏览

随着计算机技术的发展和大规模数据处理的兴起,数据库已经成为各行各业中的重要应用之一。但是,随之而来的并发访问也带来了一些问题,比如数据安全性和数据一致性问题。为了解决这些问题,数据库引入了锁机制。

本文将从以下几个方面进行介绍:数据库锁的基本概念、锁的类型、锁的操作方式、锁的粒度以及锁管理等内容。

一、数据库锁的基本概念

数据库锁是一种用于划分数据的访问权限并防止并发访问冲突的机制,其目的是保证数据的安全性和一致性。当一个事务对数据库进行操作时,必须获得相应的锁才能执行操作,其他事务则必须等待。

二、锁的类型

数据库锁可以分为共享锁和排他锁两种类型。

1. 共享锁:共享锁是一种允许多个事务同时读取同一份数据的锁,在共享锁被占用的情况下,其他事务只能获取共享锁,而不能获取排它锁。因此,共享锁可用于读取数据,但不能用于修改数据。

2. 排他锁:排他锁是一种只允许一个事务进行写操作的锁,在排他锁被占用的情况下,其他事务无法获取共享锁和排它锁。因此,排他锁可用于修改数据,但不允许其他事务同时读写。

三、锁的操作方式

数据库锁可以通过两种方式进行操作:显式锁和隐式锁。

1. 显式锁:使用显式锁机制的事务需要通过特定的命令明确地请求和释放锁。显式锁机制需要事务在读取或更新数据时添加锁,同时在提交或回滚事务时释放锁。这种方式比较灵活,但是需要手动操作,不太容易实现。

2. 隐式锁:使用隐式锁机制的事务不需要手动请求和释放锁,锁的管理由数据库系统自动完成。这种方式通常通过数据库管理系统的并发控制机制实现,比较方便,但是缺乏灵活性。

四、锁的粒度

数据库锁是根据数据的粒度进行划分的,常见的锁粒度包括行级锁、表级锁和页面级锁。

1. 行级锁:行级锁是对单条记录进行加锁,只有当其他用户想要修改相同的记录时,该记录才会被锁定。这种锁粒度最细,但是对于大规模的数据操作来说,系统开销比较大。

2. 表级锁:表级锁是对整张表进行加锁,只有当其他用户想要修改相同的表时,该表才会被锁定。这种锁粒度更大,但是对于大规模的数据操作来说,系统开销比较小。

3. 页面级锁:页面级锁是在页面级别(通常为数据页)上进行加锁,只有当其他用户想要修改相同的页面时,该页面才会被锁定。这种锁粒度介于行级锁和表级锁之间,比较适合处理中等规模的数据操作。

五、锁管理

锁管理是确保数据库锁机制有效运行的关键之一。在数据库中,锁管理的任务通常由锁管理器来处理。

锁管理器的主要任务包括锁的申请和释放、锁的处理和冲突检测。为了确保锁机制的有效性和高效性,锁管理器需要实现以下几个方面的功能:

1. 死锁检测:当两个或多个事务交替持有锁并互相等待对方的资源时,称为死锁。为了避免死锁的发生,锁管理器需要实现死锁检测功能。

2. 事务隔离级别:事务隔离级别指在一个事务执行过程中,它可以看到其他事务的修改的程度。为了确保事务隔离级别的有效性,锁管理器需要实现对事务隔离级别的支持。

3. 锁粒度管理:锁粒度管理是指对锁进行管理的过程。为了能够对不同粒度的锁进行管理,锁管理器需要实现粒度控制和锁级别管理功能。

数据库锁是事务处理过程中的重要机制,可以确保数据的一致性和安全性。锁的类型包括共享锁和排它锁两种,锁的操作方式包括显式锁和隐式锁两种,锁的粒度包括行级锁、表级锁和页面级锁,锁管理是确保锁机制有效运行的关键之一。

相关问题拓展阅读:

Oracle数据库锁的常用类型有哪些

Oracle数据库的锁类型

根据保护的对象不同,Oracle数据库锁可以分为以下几大类:DML锁(data locks,数据锁),用于保护数据的完整性;DDL锁(dictionary locks,字典锁),用于保护数据库对象的结构,如表、索引等的结构定义;内部锁和闩(internal locks and latches),保护数据库的内部结构。

DML锁的目的在于保证并况下的数据完整性,本文主要讨论DML锁。在Oracle数据库中,DML锁主要包括TM锁和TX锁,其中TM锁称为表级锁,TX锁称为事务锁或行级锁。

当Oracle执行DML语句时,系统自动在所要操作的表上申请TM类型的锁。当TM锁获得后,系统再自动申请TX类型的锁,并将实际锁定的数据行的锁标志位进行置位。这样在事务加锁前检查TX锁相容性时就不用再逐行检查锁标志,而只需检查TM锁模式的相容性即可,大大提高了系统的效率。TM锁包括了SS、SX、S、X等多种模式,在数据库中用0-6来表示。不同的Sql操作产生不同类型的TM锁。如表1所示。

在数据行上只有X锁(排他锁)。在 Oracle数据库中,当一个事务首次发起一滚粗个DML语句时就获得一个TX锁,该锁保持到事务被提交或回滚。当两个或多个会话在表的同一条记录上执行DML语句时,之一个会话在该条记录上加锁,其他的会话处于等待状态。当之一个会话提交后,TX锁被释放,其他会话才可以加锁。

当Oracle数据库发生TX锁等待时,如果不及时处理常常会引起Oracle数据库挂起,或导致仿帆死锁的发生,产生ORA-60的错误。这些现象都会对实际应用产生极大的危害,如长时间未响应,大量事务失败等。

TX锁等待的分析

在介绍了有关地Oracle数据库锁的种类后,下面讨论如何有效地监控和解决锁等待现象,及在产生死锁时如何定位死锁的原因。

监控锁的相关视图 数据字典是Oracle数据库的重要组成部分,用户可以通过查询数据字典视图来获得数据库的信息。和锁相关的数据字典视图如表2所示。

TX锁等待的监控和解决在日常工作中,如果发现在执行某条SQL时数据库长时间没有响应,很可能是产生了TX锁等待的现象。为解决这个问题,首先应该找出持锁的事务,然后再进行相关的处理,如提交事务或强行中断事务。

死锁的监控和解决在数据库中,当两个或多个会话请求同一个资源时会产生死锁的现象。死锁的常见类型是行级锁死锁和页级锁死锁,Oracle数据库中一般使用行级锁。下面主要讨论行级锁的死锁现象。

当Oracle检测到死锁产生时,中断并回滚死锁相关语句的执行,报ORA-00060的错误并记录在数据库的日志文件alertSID.log中。同时在user_dump_dest下产生了一个跟踪文件,详细描述死锁的相关信息。

在日常工作中,如果发现在日志文件中记录了ora-00060的错误信息,则表明产生了死锁。这时需要找到对应备备雹的跟踪文件,根据跟踪文件的信息定位产生的原因。

如果查询结果表明,死锁是由于bitmap索引引起的,将IND_T_ProDUCT_HIS_STATE索引改为normal索引后,即可解决死锁的问题。

表1 Oracle的TM锁类型

锁模式 锁描述 解释 SQL操作

1 NULL 空 SELECT

2 SS(Row-S) 行级共享锁,其他对象只能查询这些数据行 Select for update、Lock for update、Lock row share

3 SX(Row-X) 行级排它锁,在提交前不允许做DML操作 Insert、Update、Delete、Lock row share

4 S(Share) 共享锁 Create index、Lock share

5 SSX(S/Row-X) 共享行级排它锁 Lock share row exclusive

6 X(Exclusive) 排它锁 Alter table、Drop able、Drop index、Truncate table 、Lock exclusive

表2 数据字典视图说明

视图名 描述 主要字段说明

v$session 查询会话的信息和锁的信息。 sid,serial#:表示会话信息。

program:表示会话的应用程序信息。

row_wait_obj#:表示等待的对象。

和dba_objects中的object_id相对应。

v$session_wait 查询等待的会话信息。 sid:表示持有锁的会话信息。

Seconds_in_wait:表示等待持续的时间信息

Event:表示会话等待的事件。

v$lock 列出系统中的所有的锁。 Sid:表示持有锁的会话信息。

Type:表示锁的类型。值包括TM和TX等。

ID1:表示锁的对象标识。

lmode,request:表示会话等待的锁模式的信

息。用数字0-6表示,和表1相对应。

dba_locks 对v$lock的格式化视图。 Session_id:和v$lock中的Sid对应。

Lock_type:和v$lock中的type对应。

Lock_ID1: 和v$lock中的ID1对应。

Mode_held,mode_requested:和v$lock中

的lmode,request相对应。

v$locked_object 只包含DML的锁信息,包括回滚段和会话信息。 Xidusn,xidslot,xidsqn:表示回滚段信息。和

v$transaction相关联。

Object_id:表示被锁对象标识。

Session_id:表示持有锁的会话信息。

Locked_mode:表示会话等待的锁模式的信

息,和v$lock中的lmode一致。

col owner for a12

col object_name for a16

select b.owner,b.object_name,l.session_id,l.locked_mode

from v$locked_object l, dba_objects b

where b.object_id=l.object_id;

select t2.username,t2.sid,t2.serial#,t2.logon_time

from v$locked_object t1,v$session t2

where t1.session_id=t2.sid order by t2.logon_time;

如果有长期出现的一列,可能是没有释放的锁。我们可以用下面SQL语句杀掉长期没有释放非正常的锁:

alter system kill session ‘sid,serial# ‘;

如果出现了锁的问题, 某个DML操作可能等待很久没有反应。

当你采用的是直接连接数据库的方式,也不要用OS系统命令 $kill process_num 或者 $killprocess_num来终止用户连接,因为一个用户进程可能产生一个以上的锁, 杀OS进程并不能彻底清除锁的问题

数据库与操作系统一样,是一个多用户使用的共享资源。 当多个用户并发地存取数据时,在数据库中就会发生多个事务同时存取同一数据地情况。 若对并发操作不加控制就可能会读取和存储不正确地数据,破坏数据库地一致性。 加锁时实现数据库并发控制地一个非常重要地技术。 在实际应用中经常会遇到地与锁相关地异常情况,当两个事务需要一组有冲突的锁,而不能将事务继续下去的话,就会出现死锁,严重影响应用的正常执行。

在数据库中有两种基本的锁类型:排它锁(Exclusive Locks,即X锁)和共享锁(即S锁)。当数据对象被加上排它锁时,其他的事务不能不能对它读取和修改。加了共享锁的数据对象可以被其他事务读取,但不能修改。数据库利用这两种基本的锁类型来对数据库的事务进行并发控制。

死锁的之一种情况:

一个用户A访问表A(锁住了表A),然后又访问表B; 另一个用户B访问表B(锁住了表B),然后企图访问表A;这时用户A由于用户B已经锁住表B,它必须等待用户B释放表B才能继续,同样用户B要等用户A释放表A才能继续,这就死锁产生了。

解决方法:

这种死锁比较常见,是由于程序的BUG产生的,除了调整程序的逻辑没有其它的办法。仔细分析程序的逻辑,对于数据库的多表操作时,尽量按照同样的顺序进行处理,尽量避免同时锁定两个资源,如操作A和B两张表时,总是按先A后B的顺序处理,必须同时锁定两个资源时,要保证在任何时刻都应该按照相同的顺序来锁定资源。

死锁的第二种情况

用户A查询一条记录,然后修改该条记录;这时用户B修改该条记录,这时用户A的事务里锁的性质由查询的共享锁企图上升到独占锁,而用户B里的独占锁由于A有共享锁存在必须等A释放掉共享锁,而A由于B的独占锁而无法上升到独占锁也就不可能释放共享锁,于是出现了死锁。这种死锁比较隐蔽,但在稍大点的项目种经常发生,如在某项目中,页面上的按钮点击后,没有使按钮立刻失效,使得用户会多次快速点击同一按钮,这样同一段代码对数据库同一条记录进行多次操作,很容易就出现这种死锁的情况。

解决方法:

1、对于按钮等控件,点击后使其立刻失效,不让用户重复点击,避免对同时对同一条记录操作。

2、使用乐观锁进行控制。乐观锁大多是基于数据版本(version)记录机制实现。即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库增加一个“version”字段来实现。读取处数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交的数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。乐观锁机制避免了长事务中的数据库加锁开销(用户A和用户B操作过程中,都没有对数据库加锁),大大提升了大并发量下的系统整体性表现。 Hibernate在其数据访问引擎中内置了乐观锁实现。需要注意的是,由于乐观锁机制是我们的系统中实现,来自外部系统的用户更新操作不受我们系统的控制,因此可能会造成脏数据被更新到数据库中。

3、使用悲观锁进行控制。悲观锁大多数情况下依靠数据库的锁机制实现,如Oracle的select…….for update语句,以保证操作更大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销往往无法承受。如一个金融系统,当某个操作员读取用户的数据,并在读出的用户数据的基础上进行修改时(如更改用户帐户余额),如果采用悲观锁机制,也就意味整个操作过程中(从操作员读出数据、开始修改直至提交修改结果的全过程,甚至还包括操作员中途去煮咖啡的时间),数据库记录始终处于加锁状态,可以想见,如果面对成百上千个并发,这样的情况将导致灾难性的结果。所以,采用悲观锁进行控制时一定要考虑清楚。

死锁的第三种情况

如果在事务种执行了一条不满足条件的update语句,则执行全表扫描,把行级锁上升为表级锁,多个这样的事务执行之后,就很容易发生死锁和阻塞。类似的情况还有当表种的数据量非常庞大而索引建的过少或不合适的时候,使得经常发生全表扫描,最终应用系统会越来越慢,最终发生阻塞或死锁。

解决方法:

SQL语句中不要使用太复杂的关联多表的查询;使用“执行计划”对SQL语句进行 分析,对于有全表扫描的SQL语句,建立相应的索引进行优化。

***查询死锁表以及解锁表***

通过select * from v$locked_object

可以获得被锁的对象的object_id及产生锁的会话sid,通过查询结果中的object_id,可以查询到具体被锁的对象。

锁有以下几种模式:

1:null 空

2:Row-S 行共享(RS / S锁):共享表锁

3:Row-X 行专用(RX / X锁):用于行的修改

4:Share 共享锁(S):阻止其他DML操作

5:S/Row-X 共享行专用(SRX):阻止其他事务操作

6:exclusive 专用(X):独立访问使用

数字越大锁级别越高, 影响的操作越多。

一般的查询语句如select … from … ;是小于2的锁, 有时会在v$locked_object出现。

select … from … for update; 是2的锁。

当对话使用for update子串打开一个游标时,

所有返回集中的数据行都将处于行级(Row-X)独占式锁定,

其他对象只能查询这些数据行,不能进行update、delete或select…for update操作。

insert / update / delete … ; 是3的锁。

没有commit之前插入同样的一条记录会没有反应,

因为后一个3的锁会一直等待上一个3的锁, 我们必须释放掉上一个才能继续工作。

创建索引的时候也会产生3,4级别的锁。

locked_mode为2,3,4不影响DML(insert,delete,update,select)操作,

但DDL(alter,drop等)操作会提示ora-00054错误。

有主外键约束时 update / delete … ; 可能会产生4,5的锁。

DDL语句时是6的锁。

以DBA角色, 查看当前数据库里锁的情况可以用如下SQL语句:

select object_id,session_id,locked_mode from v$locked_object;

select t2.username,t2.sid,t2.serial#,t2.logon_time

from v$locked_object t1,v$session t2

where t1.session_id=t2.sid order by t2.logon_time;

如果有长期出现的一列,可能是没有释放的锁。

我们可以用下面SQL语句杀掉长期没有释放非正常的锁:

syase数据库,行锁,页锁,全页锁定的区别,加锁有什么作用?萌新,请大佬们用通俗的话解答一下

1、全页升敏亩锁(allpages lock) 对拿茄查询的表及索引页加锁,也就是table lock

2、页锁 (data lock) 对所查询的结果所在页加锁,对索引不加锁

3、行锁 (row lock)吵森 对某行数据加锁

好像一个lock占用的内存为120byte!

锁只是一种保护机制,并不影响数据存储!

oracle没有页锁,和其他数喊兄世据库的并发机制不一样oracle基于多版本机制、意尘巧向锁,提供高郑肢并发能力

数据库锁解析

你才二十多岁,没遇到喜欢的人很正常,往后你会发现,大概是遇不到了。如果一个人秒回了你,也只能说明这个人在玩手机而已。等你以后老了,走不动了,我就每天纯闷陪用轮椅推你到广场上去,让你看着我和别的老头跳舞。等你以后老了,走不动了,我就每天用轮椅推做蠢你到广场上去,让你看着我和别的老头跳舞。等你以后老了,走不动了,我就每天用轮椅推你到广场上去,罩仔让你看着我和别的老头跳舞。

关于数据库中的锁定义的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。

香港服务器首选树叶云,2H2G首月10元开通。树叶云(www.IDC.Net)提供简单好用,价格厚道的香港/美国云 服务器 独立服务器。IDC+ISP+ICP资质。ARIN和APNIC会员。成熟技术团队15年行业经验。


deadlocks(死锁)是什么?

在两个或多个任务中,如果每个任务锁定了其他任务试图锁定的资源,此时会造成这些任务永久阻塞,从而出现死锁。 例如:事务 A 获取了行 1 的共享锁。 事务 B 获取了行 2 的共享锁。 现在,事务 A 请求行 2 的排他锁,但在事务 B 完成并释放其对行 2 持有的共享锁之前被阻塞。 现在,事务 B 请求行 1 的排他锁,但在事务 A 完成并释放其对行 1 持有的共享锁之前被阻塞。 事务 A 必须在事务 B 完成之后才能完成,但事务 B 被事务 A 阻塞。 这种情况也称为循环依赖关系:事务 A 依赖于事务 B,而事务 B 又依赖于事务 A,从而形成了一个循环。 除非某个外部进程断开死锁,否则死锁中的两个事务都将无限期等待下去。 Microsoft SQL Server Database Engine 死锁监视器定期检查陷入死锁的任务。 如果监视器检测到循环依赖关系,将选择其中一个任务作为牺牲品,然后终止其事务并提示错误。 这样,其他任务就可以完成其事务。 对于事务以错误终止的应用程序,它还可以重试该事务,但通常要等到与它一起陷入死锁的其他事务完成后执行。 在应用程序中使用特定编码约定可以减少应用程序导致死锁的机会。 有关详细信息,请参阅将死锁减至最少。 死锁经常与正常阻塞混淆。 事务请求被其他事务锁定的资源的锁时,发出请求的事务一直等到该锁被释放。 默认情况下,SQL Server 事务不会超时(除非设置了 LOCK_TIMEOUT)。 因为发出请求的事务未执行任何操作来阻塞拥有锁的事务,所以该事务是被阻塞,而不是陷入了死锁。 最后,拥有锁的事务将完成并释放锁,然后发出请求底事务将获取锁并继续执行。 死锁有时称为抱死。 不只是关系数据库管理系统,任何多线程系统上都会发生死锁,并且对于数据库对象的锁之外的资源也会发生死锁。 例如,多线程操作系统中的一个线程要获取一个或多个资源(例如,内存块)。 如果要获取的资源当前为另一线程所拥有,则第一个线程可能必须等待拥有线程释放目标资源。 这就是说,对于该特定资源,等待线程依赖于拥有线程。 在数据库引擎 实例中,当获取非数据库资源(例如,内存或线程)时,会话会死锁。 在上图中,对于 Part 表锁资源,事务 T1 依赖于事务 T2。 同样,对于 Supplier 表锁资源,事务 T2 依赖于事务 T1。 因为这些依赖关系形成了一个循环,所以在事务 T1 和事务 T2 之间存在死锁。

SQL Server数据库表锁定原理以及如何解除锁定

1. 数据库表锁定原理 1.1 目前的C/S,B/S结构都是多用户访问数据库,每个时间点会有成千上万个user来访问DB,其中也会同时存取同一份数据,会造成数据的不一致性或者读脏数据.1.2 事务的ACID原则1.3 锁是关系数据库很重要的一部分, 数据库必须有锁的机制来确保数据的完整和一致性. 1.3.1 SQL Server中可以锁定的资源:1.3.2 锁的粒度:1.3.3 锁的升级: 锁的升级门限以及锁升级是由系统自动来确定的,不需要用户设置. 1.3.4 锁的类型: (1) 共享锁: 共享锁用于所有的只读数据操作. (2) 修改锁: 修改锁在修改操作的初始化阶段用来锁定可能要被修改的资源,这样可以避免使用共享锁造成的死锁现象 (3) 独占锁: 独占锁是为修改数据而保留的。 它所锁定的资源,其他事务不能读取也不能修改。 独占锁不能和其他锁兼容。 (4) 架构锁 结构锁分为结构修改锁(Sch-M)和结构稳定锁(Sch-S)。 执行表定义语言操作时,SQL Server采用Sch-M锁,编译查询时,SQL Server采用Sch-S锁。 (5) 意向锁 意向锁说明SQL Server有在资源的低层获得共享锁或独占锁的意向。 (6) 批量修改锁 批量复制数据时使用批量修改锁 1.3.4 SQL Server锁类型 (1) HOLDLOCK: 在该表上保持共享锁,直到整个事务结束,而不是在语句执行完立即释放所添加的锁。 (2) NOLOCK:不添加共享锁和排它锁,当这个选项生效后,可能读到未提交读的数据或“脏数据”,这个选项仅仅应用于SELECT语句。 (3) PAGLOCK:指定添加页锁(否则通常可能添加表锁)。 (4) READCOMMITTED用与运行在提交读隔离级别的事务相同的锁语义执行扫描。 默认情况下,SQL Server 2000 在此隔离级别上操作。 (5) READPAST: 跳过已经加锁的数据行,这个选项将使事务读取数据时跳过那些已经被其他事务锁定的数据行,而不是阻塞直到其他事务释放锁, READPAST仅仅应用于READ COMMITTED隔离性级别下事务操作中的SELECT语句操作。 (6) READUNCOMMITTED:等同于NOLOCK。 (7) REPEATABLEREAD:设置事务为可重复读隔离性级别。 (8) ROWLOCK:使用行级锁,而不使用粒度更粗的页级锁和表级锁。 (9) SERIALIZABLE:用与运行在可串行读隔离级别的事务相同的锁语义执行扫描。 等同于 HOLDLOCK。 (10) TABLOCK:指定使用表级锁,而不是使用行级或页面级的锁,SQL Server在该语句执行完后释放这个锁,而如果同时指定了HOLDLOCK,该锁一直保持到这个事务结束。 (11) TABLOCKX:指定在表上使用排它锁,这个锁可以阻止其他事务读或更新这个表的数据,直到这个语句或整个事务结束。 (12) UPDLOCK :指定在读表中数据时设置更新 锁(update lock)而不是设置共享锁,该锁一直保持到这个语句或整个事务结束,使用UPDLOCK的作用是允许用户先读取数据(而且不阻塞其他用户读数据),并且保证在后来再更新数据时,这一段时间内这些数据没有被其他用户修改。 2. 如何解除表的锁定,解锁就是要终止锁定的那个链接,或者等待该链接事务释放. 2.1 Activity Monitor可以通过Wait Type, Blocked By栏位查看到,SPID 54 被SPID 53 阻塞. 可以右键Details查到详细的SQL 语句,或Kill掉这个进程. 2.2 SQL Server提供几个DMV,查看locks _exec_requests _tran_locks _os_waiting_tasks _tran_database_transactions (1) select * from _tran_locks where reSource_type<>DATABASE --and resource_database_id=DB_ID()

mysql悲观锁和乐观锁的区别

悲观锁与乐观锁是两种常见的资源并发锁设计思路,也是并发编程中一个非常基础的概念。 本文将对这两种常见的锁机制在数据库数据上的实现进行比较系统的介绍。 悲观锁(Pessimistic Lock)悲观锁的特点是先获取锁,再进行业务操作,即“悲观”的认为获取锁是非常有可能失败的,因此要先确保获取锁成功再进行业务操作。 通常所说的“一锁二查三更新”即指的是使用悲观锁。 通常来讲在数据库上的悲观锁需要数据库本身提供支持,即通过常用的select … for update操作来实现悲观锁。 当数据库执行select for update时会获取被select中的数据行的行锁,因此其他并发执行的select for update如果试图选中同一行则会发生排斥(需要等待行锁被释放),因此达到锁的效果。 select for update获取的行锁会在当前事务结束时自动释放,因此必须在事务中使用。 这里需要注意的一点是不同的数据库对select for update的实现和支持都是有所区别的,例如oracle支持select for update no wait,表示如果拿不到锁立刻报错,而不是等待,mysql就没有no wait这个选项。 另外mysql还有个问题是select for update语句执行中所有扫描过的行都会被锁上,这一点很容易造成问题。 因此如果在mysql中用悲观锁务必要确定走了索引,而不是全表扫描。 乐观锁(Optimistic Lock)乐观锁的特点先进行业务操作,不到万不得已不去拿锁。 即“乐观”的认为拿锁多半是会成功的,因此在进行完业务操作需要实际更新数据的最后一步再去拿一下锁就好。 乐观锁在数据库上的实现完全是逻辑的,不需要数据库提供特殊的支持。 一般的做法是在需要锁的数据上增加一个版本号,或者时间戳,然后按照如下方式实现:1. SELECT data AS old_data, version AS old_version FROM …;2. 根据获取的数据进行业务操作,得到new_data和new_version3. UPDATE SET data = new_data, version = new_version WHERE version = old_versionif (updated row > 0) {// 乐观锁获取成功,操作完成} else {// 乐观锁获取失败,回滚并重试}乐观锁是否在事务中其实都是无所谓的,其底层机制是这样:在数据库内部update同一行的时候是不允许并发的,即数据库每次执行一条update语句时会获取被update行的写锁,直到这一行被成功更新后才释放。 因此在业务操作进行前获取需要锁的数据的当前版本号,然后实际更新数据时再次对比版本号确认与之前获取的相同,并更新版本号,即可确认这之间没有发生并发的修改。 如果更新失败即可认为老版本的数据已经被并发修改掉而不存在了,此时认为获取锁失败,需要回滚整个业务操作并可根据需要重试整个过程。 总结乐观锁在不发生取锁失败的情况下开销比悲观锁小,但是一旦发生失败回滚开销则比较大,因此适合用在取锁失败概率比较小的场景,可以提升系统并发性能乐观锁还适用于一些比较特殊的场景,例如在业务操作过程中无法和数据库保持连接等悲观锁无法适用的地方

本文版权声明本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请联系本站客服,一经查实,本站将立刻删除。

发表评论

热门推荐