ICode9

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

MySQL锁

2021-07-16 14:34:17  阅读:160  来源: 互联网

标签:行级 加锁 记录 行锁 并发 MySQL 表级


一.什么是锁

数据库的锁是为了对共享资源进行并发访问,提供数据的完整性和一致性,这样才能保证在高并发场景下,访问数据库时,数据不会出现问题.

二.锁机制

1.按锁的粒度划分:行级锁、表级锁、页级锁、间隙锁

MyISAM和MEMORY采用表级锁(table-level locking)
InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁
BDB采用页面锁(page-level locking)或表级锁,默认为页面锁

默认情况下,表锁和行锁都是自动获得的, 不需要额外的命令。

1)行级锁

描述:
行级锁是mysql中锁粒度最小的一种锁。表示只针对当前操作的行进行加锁。行级锁分为共享锁和排他锁

特点:
开销大,加锁慢,会出现死锁。发生锁冲突的概率最低,并发度也最高。

InnoDB有三种行锁的算法:

1,Record Lock(记录锁):单个行记录上的锁。这个也是我们日常认为的行锁。

2,Gap Lock(间隙锁):间隙锁,锁定一个范围,但不包括记录本身(只不过它的锁粒度比记录锁的锁整行更大一些,他是锁住了某个范围内的多个行,包括根本不存在的数据)。GAP锁的目的,是为了防止同一事务的两次当前读,出现幻读的情况。该锁只会在隔离级别是RR或者以上的级别内存在。间隙锁的目的是为了让其他事务无法在间隙中新增数据。

3,Next-Key Lock(临键锁):它是记录锁和间隙锁的结合,锁定一个范围,并且锁定记录本身。对于行的查询,都是采用该方法,主要目的是解决幻读的问题。next-key锁是InnoDB默认的锁

next-Key锁规定是左开右闭区间,效果相当于一个记录锁加一个间隙锁。当next-key lock加在某索引上,则该记录和它前面的区间都被锁定
假设有记录1, 3, 5, 7,现在记录5上加next-key lock,则会锁定区间(3, 5],任何试图插入到这个区间的记录都会阻塞

2)表级锁

描述:
表级锁是mysql中锁定粒度最大的一种锁,表示对当前操作的整张表加锁.
最常使用的MyISAM与InnoDB都支持表级锁。
表级锁分为表共享读锁(共享锁)与表独占写锁(排他锁).

特点:
开销小,加锁快,不会出现死锁。发生锁冲突的概率最高,并发度也最低。

LOCK TABLE my_table_name READ;  
用读锁锁表,会阻塞其他事务修改表数据。
LOCK TABLE my_table_name WRITE; 
用写锁锁表,会阻塞其他事务读和写。

MyISAM在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执行更新操作(UPDATE、DELETE、INSERT等)前,会自动给涉及的表加写锁,这个过程并不需要用户干预,因此,用户一般不需要直接用LOCK TABLE命令给MyISAM表显式加锁。
MyISAM 表的读操作与写操作之间,以及写操作之间是串行的。当一个线程获得对一个表的写锁后, 只有持有锁的线程可以对表进行更新操作。 其他线程的读、 写操作都会等待,直到锁被释放为止。

3)页级锁

描述:
页级锁是 MySQL 中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突少,但速度慢。因此,采取了折中的页级锁,一次锁定相邻的一组记录。BDB 支持页级锁。

特点:
开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。

2.按照锁的共享策略来分:共享锁、排他锁、意向共享锁、意向排他锁

1)读锁(共享锁):Shared Locks(S锁),其他事务可以读,但不能写

2)写锁(排它锁):Exclusive Locks(X锁),其他事务不能读取,也不能写

3)IS锁:意向共享锁、Intention Shared Lock。当事务准备在某条记录上加S锁时,需要先在表级别加一个IS锁。

4)IX锁:意向排他锁、Intention Exclusive Lock。当事务准备在某条记录上加X锁时,需要先在表级别加一个IX锁。

IS、IX锁是表级锁,它们的提出仅仅为了在之后加表级别的S锁和X锁时可以快速判断表中的记录是否被上锁,以避免用遍历的方式来查看表中有没有上锁的记录。
就是说当对一个行加锁之后,如果有打算给行所在的表加一个表锁,必须先看看该表的行有没有被加锁,否则就会出现冲突。
IS锁和IX锁就避免了判断表中行有没有加锁时对每一行的遍历。直接查看表有没有意向锁就可以知道表中有没有行锁。 注意:如果一个表中有多个行锁,他们都会给表加上意向锁,意向锁和意向锁之间是不会冲突的。

3.按加锁策略上分:乐观锁和悲观锁

1)悲观锁:

认为对于同一个数据的并发操作,一定是会发生修改的(或者增删改多,查少),哪怕没有修改,也会认为修改。

因此对于同一个数据的并发操作,悲观锁采取加锁的形式。悲观的认为,不加锁的并发操作一定会出问题。

2)乐观锁:

则认为对于同一个数据的并发操作,是不会发生修改的(或者增删改少,查多)。

在更新数据的时候,会采用不断尝试更新的方式来修改数据。也就是先不管资源有没有被别的线程占用,直接取申请操作,如果没有产生冲突,那就操作成功,如果产生冲突,有其他线程已经在使用了,那么就不断地轮询。

乐观的认为,不加锁的并发操作是没有事情的。就是通过记录一个数据历史记录的多个版本,如果修改完之后发现有冲突再将版本返回到没修改的样子,乐观锁就是不加锁。好处就是减少上下文切换,坏处是浪费CPU时间。

 

 

标签:行级,加锁,记录,行锁,并发,MySQL,表级
来源: https://www.cnblogs.com/Baker-Street/p/15019971.html

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

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

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

ICode9版权所有