带你了解mysql中锁的概念
Posted 捶捶自己
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了带你了解mysql中锁的概念相关的知识,希望对你有一定的参考价值。
锁
为什么需要锁?
凡是遇到新知识,必问为什么?没别的,就是喜欢深入(当然是因为需要造航母啊)~
数据库锁出现的原因是为了处理并发问题,因为数据库是一个多用户共享的资源,当出现并发的时候,就会导致出现各种各样奇怪的问题,就像程序代码一样,出现多线程并发的时候,如果不做特殊控制的话,就会出现意外的事情,比如“脏“数据、修改丢失等问题。所以数据库并发需要使用事务来控制,事务并发问题需要数据库锁来控制,所以数据库锁是跟并发控制和事务联系在一起的。
锁的分类
在mysql中,可以按照范围来区分锁:
- 全局锁
- 表级锁
- 行锁
全局锁
顾名思义,全局锁就是给全局上的一把锁,能够对整个数据库造成影响的锁。
flush tables with read lock
只要执行了上述命令,整个数据库就变为可读状态了,其他线程的所有操作都会被堵塞。
我这里用一个数据进行验证一下:
mysql> select * from t_user;
+----+-----------+------+
| id | name | age |
+----+-----------+------+
| 1 | 张三 | 18 |
| 3 | 王五 | 17 |
| 4 | Tom | 18 |
+----+-----------+------+
3 rows in set (0.01 sec)
mysql> flush tables with read lock;
Query OK, 0 rows affected (0.00 sec)
这时,开启一个新的线程,并且修改表中数据会发生堵塞吗?
mysql> update go_db.t_user set age = 66 where name = 'Tom';
....
虽然可以读取数据,但是只要执行增删改这些操作(修改表等操作也会被堵塞)就会发生堵塞。
unlock tables
执行该条命令即可解除全局锁,如果会话断开全局锁也是会自动解除的。
那么这样一个导致全局都只能进行读取,而不能进行增删改等操作的锁有什么用呢?
全局锁的应用
全局锁主要用于数据库全库逻辑的备份,在备份期间肯定不能有对数据库造成影响的语句发生,唯一可以不会造成影响的就是读操作了。
全局锁的缺点
显而易见,全局加锁用于备份,而备份数据这个时间可不短。那么在备份的时间里,所有的语句都没法执行,甚至全部处于堵塞状态。这就先不考虑堵塞结束后数据库会不会崩溃,需要先考虑的问题是只能读的情况下业务岂不是全部没法执行了吗。那么全局锁必须要业务停下来才能备份的话,岂不又是一个大问题?
如何避免全局锁的缺点呢?
还记得事务的隔离性中有一个级别可以单独有一个数据空间进行事务处理吗?没错就是可重复读。
如果数据库的存储引擎支持事务,并且支持事务的可重复读这个隔离级别。那么他就可以在备份数据库之前先开启Read View
。然后在Read View
下进行一系列操作。
在可重复读的环境下,事务之外的任何操作都不会影响到该事务内的数据变化。在备份期间可以一直使用这个空间。
表级锁
在Mysql中被称为表级锁的有这么几种:
- 表锁
- 元数据锁(MDL)
- 意向锁
- AUTO-INC锁
表锁
表锁锁定有两种方式,一种是读锁,一种是写锁。
//表级别的共享锁,也就是读锁;
lock tables t_student read;
//表级别的独占锁,也就是写锁;
lock tables t_stuent write;
两种锁的解锁的方式和全局锁一样。
当使用读锁的时候,整个数据表都只能进行查询操作。一旦有写操作就会被堵塞,等待读锁的释放。
当使用写锁的时候,整个数据表无论读写都会被堵塞,等待写锁的资源释放。
如果没有主动释放锁,当会话结束之后,锁也会被释放掉。
元数据锁
**元数据锁(MDL)**是一个隐式的锁。意思就是不需要主动开启,它会自动启用。
那么什么情况下元数据锁会主动启动呢?
- 当你对一张表进行CRUD的时候,就会对这个表开启MDL写锁,其余读操作均被阻塞。
- 当你对一张表进行结构变更的时候,就会对这个表开启MDL读锁,其余读写操作全被堵塞。
当一个执行操作结束时或者会话结束时,MDL锁就会被释放。
当有一个事务执行时,会在事务提交的时候进行释放。也就是说只要事务还没有提交,MDL已经开启了,那么他就一直不会进行释放。因此也出现了一个隐患问题。
在事务提交的时候才会释放的MDL锁带来的隐患
假如A线程开启了事务,并且进行了查询操作触发了MDL读锁。
B线程进行了查询操作并且没有堵塞,因为两方互不影响,MDL读锁不会阻塞读锁。
这时C线程对表结构进行了更改,发现A线程事务还没有提交,触发MDL写锁,进行堵塞。
自此之后的CRUD线程来一个就会被堵塞一个,直到A线程提交事务或者线程过载数据库系统崩溃。
为什么单个线程触发写锁之后,其他线程也没法进行读操作?
因为MDL锁是一个队列锁。所有申请MDL锁的线程会排成一个队列等待执行。而这个队列中写的优先级要高于读。一旦出现了MDL写锁,那么之后所有的CRUD操作全部都被堵塞了。
所有为了性能和安全的考虑,在进行对数据库表结构进行修改的时候,需要先查看是否有长事务在进行中。如果该事务必须执行,则只能等待执行。如果该事务的执行可以在修改结构之后,那么可以选择先kill
掉这个长事务的线程。
意向锁
意向锁其实”人如其名“,就是一个有想法,但准备行动的锁。值得注意的是:意向锁是一个表级锁
在一个数据表中,如果你想要对表里的某些记录加上 [共享锁] 或 [独占锁]的时候,你需要先去判断,这个表中是否已经加过了共享锁或者独占锁(排他锁)了。因此你需要遍历表中的所有记录,查询后发现没有这些锁的痕迹,你才能放心的加你想加的锁。
这里有一个很重要的点:就是只有获取表中的行锁时,才会需要先申请意向锁。 如果是执行 ALTER TABLE 等需要锁定整个表的语句,是不需要申请意向锁的,可以直接去申请表级 独占锁。
而在你加锁之前,还需要做一件事。来表明你需要加锁这个意向。这就是意向锁。
-
当你准备加共享锁的时候,你需要先加意向共享锁。
-
当你准备加独占锁的时候,你需要先加意向独占锁。
就因为有个想法就要去加一把锁吗?并不是,意向锁可大有用处。
还记得你在加锁之前需要先判断这个表中是否已经被加过锁这个操作吗?遍历记录是很浪费时间的,你只需要判断这个表是否有意向锁就行了。因为在加锁之前都会先加一个意向锁。
因此,意向锁的目的是为了快速判断表里是否有记录被加锁。
值得一提的是:
意向共享锁和意向独占锁是表级锁,不会和行级的共享锁和独占锁发生冲突,而且意向锁之间也不会发生冲突,只会和共享表锁(lock tables … read)和独占表锁(lock tables … write)发生冲突。
表锁和行锁是满足读读共享、读写互斥、写写互斥的。
AUTO-INC锁
大家都知道每张表中会有一个自增主键。而无论多么高频率的并行插入数据,这个自增主键永远保持 自增和连续。
能够无错误的连续且自增,正是因为AUTO-INC
锁的作用。
在一个事务进行插入数据的时候,他会先去获取到AUTO-INC
锁。等插入完毕之后再释放掉这个锁。注意,这个锁是在插入数据之后便释放的,即使在事务中也是如此。
但是在高频率的插入下,仍然会产生效率的问题。因此,在Mysql5.1.22版本之后,Innodb
引擎出现了一个新的轻量级的锁。
Innodb
存储引擎提供了一个innodb_autoinc_lock_mode
的系统变量。通过这个变量可以选择,什么时候使用AUTO-INC
锁,什么时候使用轻量级锁。
- 当
innodb_autoinc_lock_mode
= 0时,就采用AUTO-INC
锁,语句执行结束之后释放锁。 - 当
innodb_autoinc_lock_mode
= 2时,就采用轻量级锁,申请自增主键后就释放锁,并不需要等语句执行后才释放。 - 当
innodb_autoinc_lock_mode
= 1时,会分情况讨论:- 普通
insert
语句,自增锁在申请之后就马上释放; - 类似
insert … select
这样的批量插入数据的语句,自增锁还是要等语句结束后才被释放;
- 普通
行级锁
在Mysql中,是有锁的颗粒度这个概念的。所谓颗粒度就是指锁的级别,范围越大的锁,颗粒度越大,性能也就越低。
因此行级锁就是颗粒度最小的一类锁。
注:Innodb存储引擎是支持行级锁的,而Myisam存储引擎并不支持。
行级锁的类型主要有三类:
- Record Lock,记录锁,也就是仅仅把一条记录锁上;
- Gap Lock,间隙锁,锁定一个范围,但是不包含记录本身;
- Next-Key Lock:Record Lock + Gap Lock 的组合,锁定一个范围,并且锁定记录本身。
在了解行级锁之前,需要先了解两个概念:共享锁(S)和独占锁或者叫做排他锁(X)。
下面分别是两种锁的执行语句:
//对读取的记录加共享锁
select ... lock in share mode;
//对读取的记录加独占锁
select ... for update;
共享锁(S锁)满足读读共享,读写互斥。独占锁(X锁)满足写写互斥、读写互斥。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5z3zl9KS-1680535311435)(MySQL.assets/x锁和s锁.png)]
Record Lock
Record Lock
称为记录锁,锁住的是一条记录。而且记录锁是有 S 锁和 X 锁之分的:
记录锁是对索引记录的锁定,换句话说就是,记录锁只会锁定索引。
- 当一个事务对一条记录加了 S 型记录锁后,其他事务也可以继续对该记录加 S 型记录锁(S 型与 S 锁兼容),但是不可以对该记录加 X 型记录锁(S 型与 X 锁不兼容)
- 当一个事务对一条记录加了 X 型记录锁后,其他事务既不可以对该记录加 S 型记录锁(S 型与 X 锁不兼容),也不可以对该记录加 X 型记录锁(X 型与 X 锁不兼容)
当开启一个事务之后,并且对id=5的数据添加上记录锁之后。这样其他事务就无法对这条数据进行修改了。当事务提交之后该锁才会被释放掉。
Gap Lock
Gap Lock
称为间隙锁,只存在于可重复读隔离级别,目的是为了解决可重复读隔离级别下幻读的现象。
先来说一下什么是幻读:
幻读就是一个线程读取了一类数据的值之后,另一个线程增添了该类数据的值。这时总的数据量发生了变化,等到第一个线程再次区读取该类数据的值之后发现,相比之前的查询结果竟然多出来了一条数据。
因此,幻读主要注重于行的变化。
再来说说为什么间隙锁能够解决幻读:
间隙锁可以将索引id
范围进行锁定,比如锁定(3,7)之间。那么这段数据之间不能再插入一条新的数据(4,5,6)。而幻读注重行的变化,你在范围内的变化给他锁定了,那他不就无法变化了吗。
间隙锁虽然存在 X 型间隙锁和 S 型间隙锁,但是并没有什么区别,间隙锁之间是兼容的,即两个事务可以同时持有包含共同间隙范围的间隙锁,并不存在互斥关系,因为间隙锁的目的是防止插入幻影记录而提出的。
Next-Key Lock
Next-Key Lock
称为临键锁。是记录锁和间隙锁的合体形态。他会锁定这个范围,并且锁定记录本身不能被改变。
假设,表中有一个范围 id 为(3,5] 的 next-key lock,那么其他事务即不能插入 id = 4 记录,也不能修改 id = 5 这条记录。
所以,next-key lock 即能保护该记录,又能阻止其他事务将新纪录插入到被保护记录前面的间隙中。
虽然相同范围的间隙锁是多个事务相互兼容的,但对于记录锁,我们是要考虑 X 型与 S 型关系,X 型的记录锁与 X 型的记录锁是冲突的。
参考资料
MySQL InnoDB中的锁-自增锁(AUTO-INC Locks)-阿里云开发者社区 (aliyun.com)
MySQL 有哪些锁? | 小林coding (xiaolincoding.com)
快速解“锁”MySQL,拿下这7把钥匙,便能撬倒面试官 - 知乎 (zhihu.com)
Sql Server 中锁的概念
锁的概述
一. 为什么要引入锁
多个用户同时对数据库的并发操作时会带来以下数据不一致的问题:
丢失更新
A,B两个用户读同一数据并进行修改,其中一个用户的修改结果破坏了另一个修改的结果,比如订票系统
脏读
A用户修改了数据,随后B用户又读出该数据,但A用户因为某些原因取消了对数据的修改,数据恢复原值,此时B得到的数据就与数据库内的数据产生了不一致
不可重复读
A用户读取数据,随后B用户读出该数据并修改,此时A用户再读取数据时发现前后两次的值不一致
并发控制的主要方法是封锁,锁就是在一段时间内禁止用户做某些操作以避免产生数据不一致
二 锁的分类
锁的类别有两种分法:
1. 从数据库系统的角度来看:分为独占锁(即排它锁),共享锁和更新锁
MS-SQL Server 使用以下资源锁模式。
锁模式 描述
共享 (S) 用于不更改或不更新数据的操作(只读操作),如 SELECT 语句。
更新 (U) 用于可更新的资源中。防止当多个会话在读取、锁定以及随后可能进行的资源更新时发生常见形式的死锁。
排它 (X) 用于数据修改操作,例如 INSERT、UPDATE 或 DELETE。确保不会同时同一资源进行多重更新。
意向锁 用于建立锁的层次结构。意向锁的类型为:意向共享 (IS)、意向排它 (IX) 以及与意向排它共享 (SIX)。
架构锁 在执行依赖于表架构的操作时使用。架构锁的类型为:架构修改 (Sch-M) 和架构稳定性 (Sch-S)。
大容量更新 (BU) 向表中大容量复制数据并指定了 TABLOCK 提示时使用。
共享锁
共享 (S) 锁允许并发事务读取 (SELECT) 一个资源。资源上存在共享 (S) 锁时,任何其它事务都不能修改数据。一旦已经读取数据,便立即释放资源上的共享 (S) 锁,除非将事务隔离级别设置为可重复读或更高级别,或者在事务生存周期内用锁定提示保留共享 (S) 锁。
更新锁
更新 (U) 锁可以防止通常形式的死锁。一般更新模式由一个事务组成,此事务读取记录,获取资源(页或行)的共享 (S) 锁,然后修改行,此操作要求锁转换为排它 (X) 锁。如果两个事务获得了资源上的共享模式锁,然后试图同时更新数据,则一个事务尝试将锁转换为排它 (X) 锁。共享模式到排它锁的转换必须等待一段时间,因为一个事务的排它锁与其它事务的共享模式锁不兼容;发生锁等待。第二个事务试图获取排它 (X) 锁以进行更新。由于两个事务都要转换为排它 (X) 锁,并且每个事务都等待另一个事务释放共享模式锁,因此发生死锁。
若要避免这种潜在的死锁问题,请使用更新 (U) 锁。一次只有一个事务可以获得资源的更新 (U) 锁。如果事务修改资源,则更新 (U) 锁转换为排它 (X) 锁。否则,锁转换为共享锁。
排它锁
排它 (X) 锁可以防止并发事务对资源进行访问。其它事务不能读取或修改排它 (X) 锁锁定的数据。
意向锁
意向锁表示 SQL Server 需要在层次结构中的某些底层资源上获取共享 (S) 锁或排它 (X) 锁。例如,放置在表级的共享意向锁表示事务打算在表中的页或行上放置共享 (S) 锁。在表级设置意向锁可防止另一个事务随后在包含那一页的表上获取排它 (X) 锁。意向锁可以提高性能,因为 SQL Server 仅在表级检查意向锁来确定事务是否可以安全地获取该表上的锁。而无须检查表中的每行或每页上的锁以确定事务是否可以锁定整个表。
意向锁包括意向共享 (IS)、意向排它 (IX) 以及与意向排它共享 (SIX)。
锁模式 描述
意向共享 (IS) 通过在各资源上放置 S 锁,表明事务的意向是读取层次结构中的部分(而不是全部)底层资源。
意向排它 (IX) 通过在各资源上放置 X 锁,表明事务的意向是修改层次结构中的部分(而不是全部)底层资源。IX 是 IS 的超集。
与意向排它共享 (SIX) 通过在各资源上放置 IX 锁,表明事务的意向是读取层次结构中的全部底层资源并修改部分(而不是全部)底层资源。允许顶层资源上的并发 IS 锁。例如,表的 SIX 锁在表上放置一个 SIX 锁(允许并发 IS 锁),在当前所修改页上放置 IX 锁(在已修改行上放置 X 锁)。虽然每个资源在一段时间内只能有一个 SIX 锁,以防止其它事务对资源进行更新,但是其它事务可以通过获取表级的 IS 锁来读取层次结构中的底层资源。
独占锁:只允许进行锁定操作的程序使用,其他任何对他的操作均不会被接受。执行数据更新命令时,SQL Server会自动使用独占锁。当对象上有其他锁存在时,无法对其加独占锁。
共享锁:共享锁锁定的资源可以被其他用户读取,但其他用户无法修改它,在执行Select时,SQL Server会对对象加共享锁。
更新锁:当SQL Server准备更新数据时,它首先对数据对象作更新锁锁定,这样数据将不能被修改,但可以读取。等到SQL Server确定要进行更新数据操作时,他会自动将更新锁换为独占锁,当对象上有其他锁存在时,无法对其加更新锁。
2. 从程序员的角度看:分为乐观锁和悲观锁。
乐观锁:完全依靠数据库来管理锁的工作。
悲观锁:程序员自己管理数据或对象上的锁处理。
MS-SQLSERVER 使用锁在多个同时在数据库内执行修改的用户间实现悲观并发控制
三 锁的粒度
锁粒度是被封锁目标的大小,封锁粒度小则并发性高,但开销大,封锁粒度大则并发性低但开销小
SQL Server支持的锁粒度可以分为为行、页、键、键范围、索引、表或数据库获取锁
资源 描述
RID 行标识符。用于单独锁定表中的一行。
键 索引中的行锁。用于保护可串行事务中的键范围。
页 8 千字节 (KB) 的数据页或索引页。
扩展盘区 相邻的八个数据页或索引页构成的一组。
表 包括所有数据和索引在内的整个表。
DB 数据库。
四 锁定时间的长短
锁保持的时间长度为保护所请求级别上的资源所需的时间长度。
用于保护读取操作的共享锁的保持时间取决于事务隔离级别。采用 READ COMMITTED 的默认事务隔离级别时,只在读取页的期间内控制共享锁。在扫描中,直到在扫描内的下一页上获取锁时才释放锁。如果指定 HOLDLOCK 提示或者将事务隔离级别设置为 REPEATABLE READ 或 SERIALIZABLE,则直到事务结束才释放锁。
根据为游标设置的并发选项,游标可以获取共享模式的滚动锁以保护提取。当需要滚动锁时,直到下一次提取或关闭游标(以先发生者为准)时才释放滚动锁。但是,如果指定 HOLDLOCK,则直到事务结束才释放滚动锁。
用于保护更新的排它锁将直到事务结束才释放。
如果一个连接试图获取一个锁,而该锁与另一个连接所控制的锁冲突,则试图获取锁的连接将一直阻塞到:
将冲突锁释放而且连接获取了所请求的锁。
连接的超时间隔已到期。默认情况下没有超时间隔,但是一些应用程序设置超时间隔以防止无限期等待
五 SQL Server 中锁的自定义
1 处理死锁和设置死锁优先级
死锁就是多个用户申请不同封锁,由于申请者均拥有一部分封锁权而又等待其他用户拥有的部分封锁而引起的无休止的等待
可以使用SET DEADLOCK_PRIORITY控制在发生死锁情况时会话的反应方式。如果两个进程都锁定数据,并且直到其它进程释放自己的锁时,每个进程才能释放自己的锁,即发生死锁情况。
2 处理超时和设置锁超时持续时间。
@@LOCK_TIMEOUT 返回当前会话的当前锁超时设置,单位为毫秒
SET LOCK_TIMEOUT 设置允许应用程序设置语句等待阻塞资源的最长时间。当语句等待的时间大于 LOCK_TIMEOUT 设置时,系统将自动取消阻塞的语句,并给应用程序返回"已超过了锁请求超时时段"的 1222 号错误信息
示例
下例将锁超时期限设置为 1,800 毫秒。
SET LOCK_TIMEOUT 1800
3) 设置事务隔离级别。
4 ) 对 SELECT、INSERT、UPDATE 和 DELETE 语句使用表级锁定提示。
5) 配置索引的锁定粒度
可以使用 sp_indexoption 系统存储过程来设置用于索引的锁定粒度
六 查看锁的信息
1 执行 EXEC SP_LOCK 报告有关锁的信息
2 查询分析器中按Ctrl+2可以看到锁的信息
七 使用注意事项
如何避免死锁
1 使用事务时,尽量缩短事务的逻辑处理过程,及早提交或回滚事务;
2 设置死锁超时参数为合理范围,如:3分钟-10分种;超过时间,自动放弃本次操作,避免进程悬挂;
3 优化程序,检查并避免死锁现象出现;
4 .对所有的脚本和SP都要仔细测试,在正是版本之前。
5 所有的SP都要有错误处理(通过@error)
6 一般不要修改SQL SERVER事务的默认级别。不推荐强行加锁
解决问题 如何对行 表 数据库加锁
八 几个有关锁的问题
1 如何锁一个表的某一行
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SELECT * FROM table ROWLOCK WHERE id = 1
2 锁定数据库的一个表
SELECT * FROM table WITH (HOLDLOCK)
加锁语句:
sybase:
update 表 set col1=col1 where 1=0 ;
MSSQL:
select col1 from 表 (tablockx) where 1=0 ;
oracle:
LOCK TABLE 表 IN EXCLUSIVE MODE ;
加锁后其它人不可操作,直到加锁用户解锁,用commit或rollback解锁
几个例子帮助大家加深印象
设table1(A,B,C)
A B C
a1 b1 c1
a2 b2 c2
a3 b3 c3
1)排它锁
新建两个连接
在第一个连接中执行以下语句
begin tran
update table1
set A=‘aa‘
where B=‘b2‘
waitfor delay ‘00:00:30‘ --等待30秒
commit tran
在第二个连接中执行以下语句
begin tran
select * from table1
where B=‘b2‘
commit tran
若同时执行上述两个语句,则select查询必须等待update执行完毕才能执行即要等待30秒
2)共享锁
在第一个连接中执行以下语句
begin tran
select * from table1 holdlock -holdlock人为加锁
where B=‘b2‘
waitfor delay ‘00:00:30‘ --等待30秒
commit tran
在第二个连接中执行以下语句
begin tran
select A,C from table1
where B=‘b2‘
update table1
set A=‘aa‘
where B=‘b2‘
commit tran
若同时执行上述两个语句,则第二个连接中的select查询可以执行
而update必须等待第一个事务释放共享锁转为排它锁后才能执行 即要等待30秒
3)死锁
增设table2(D,E)
D E
d1 e1
d2 e2
在第一个连接中执行以下语句
begin tran
update table1
set A=‘aa‘
where B=‘b2‘
waitfor delay ‘00:00:30‘
update table2
set D=‘d5‘
where E=‘e1‘
commit tran
在第二个连接中执行以下语句
begin tran
update table2
set D=‘d5‘
where E=‘e1‘
waitfor delay ‘00:00:10‘
update table1
set A=‘aa‘
where B=‘b2‘
commit tran
同时执行,系统会检测出死锁,并中止进程
补充一点:
Sql Server2000支持的表级锁定提示
HOLDLOCK 持有共享锁,直到整个事务完成,应该在被锁对象不需要时立即释放,等于SERIALIZABLE事务隔离级别
NOLOCK 语句执行时不发出共享锁,允许脏读 ,等于 READ UNCOMMITTED事务隔离级别
PAGLOCK 在使用一个表锁的地方用多个页锁
READPAST 让sql server跳过任何锁定行,执行事务,适用于READ UNCOMMITTED事务隔离级别只跳过RID锁,不跳过页,区域和表锁
ROWLOCK 强制使用行锁
TABLOCKX 强制使用独占表级锁,这个锁在事务期间阻止任何其他事务使用这个表
UPLOCK 强制在读表时使用更新而不用共享锁
应用程序锁:
应用程序锁就是客户端代码生成的锁,而不是sql server本身生成的锁
处理应用程序锁的两个过程
sp_getapplock 锁定应用程序资源
sp_releaseapplock 为应用程序资源解锁
注意: 锁定数据库的一个表的区别
SELECT * FROM table WITH (HOLDLOCK) 其他事务可以读取表,但不能更新删除
SELECT * FROM table WITH (TABLOCKX) 其他事务不能读取表,更新和删除
SQL code
1 如何锁一个表的某一行
A 连接中执行
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
begin tran
select * from tablename with (rowlock) where id=3
waitfor delay ‘00:00:05‘
commit tran
B连接中如果执行
update tablename set colname=‘10‘ where id=3 --则要等待5秒
update tablename set colname=‘10‘ where id<>3 --可立即执行
2 锁定数据库的一个表
SELECT * FROM table WITH (HOLDLOCK)
注意: 锁定数据库的一个表的区别
SELECT * FROM table WITH (HOLDLOCK)
其他事务可以读取表,但不能更新删除
SELECT * FROM table WITH (TABLOCKX)
其他事务不能读取表,更新和删除
以上是关于带你了解mysql中锁的概念的主要内容,如果未能解决你的问题,请参考以下文章