作者:微信小助手
发布时间:2024-09-14T08:26:49
MySQL 的锁可以分成三类:总体、类型、粒度。 下面我们就来详细讲一下这些锁 悲观锁对于数据库中数据的读写持悲观态度,即在整个数据处理的过程中,他会悲观认为数据不会保持一致性,所以是会将相应的数据锁定。在数据库中,悲观锁的实现是依赖数据库提供的锁机制。 如果加上了悲观锁,那么就无法对这些数据进行读取操作。 乐观锁对于数据库的数据的读写持乐观态度,即在整个数据处理的过程中,他会很乐观的认为数据会保持一致性,所以不加锁,而是通过数据版本记录机制实现。 MySQL中的MVCC多版本控制就是乐观锁的一种实现方式。 读写又称为共享锁或者S锁(Shared Lock),针对同一份数据,可以加多个读锁而互不影响。 写锁又称为排他锁或者X锁(Exclusive Lock),如果当前写锁未释放,他会阻塞其他的写锁和读锁。 表锁也称为表级锁,就是在整个数据表上对数据进行加锁和释放锁。特点:开销小,加速快,粒度大,并发度最低,发生锁冲突概率高。 在MySQL中,有两种表锁模式:一种是表共享锁(Table Shard Lock),另一种是表独占写锁(Table Write Lock)。 当一个线程获取到一个表的读锁后,其他线程仍然可以进行读操作,但不能对表进行写操作。那么对应的如果一个线程获取到一个表的写锁后,只有这个线程可以进行读写操作,其他线程无法对表进行读写操作,直到写锁被释放为止。 在mysql中可以通过以下命令手动添加表锁 eg: 添加读表锁 eg: 添加写表锁 使用如下命令可以查看数据表上增加的锁 删除表锁: 行锁也称为行级别,就是在数据行上对数据进行加锁和释放锁。特点:开销大,加锁慢,粒度小,并发度高,锁冲突概率最小。 在mysql的InnoDB存储引擎中有两种行锁,排他锁和共享锁。 注意: 页级锁定是 MySQL 中比较独特的一种锁定级别。特点:锁定颗粒度介于行级锁定与表级锁之间,锁开销和加锁时间界于表锁和行锁之间,并发处理能力也同样是介于上面二者之间,并发度一般。 不过,随着锁定资源颗粒度的减小,应用程序的访问请求遇到锁等待的可能性也会随之降低,系统整体并发度也随之提升。 使用页级锁定的主要是 BerkeleyDB 存储引擎。 在mysql中使用范围查询的时,如果请求共享锁或者排他锁,InnoDB会给符合条件的已有数据的索引项加锁。如果键值在条件范围内,而这个范围内并不存在记录,而认为此时出现了间隙,InnoDB会对这个间隙进行加锁,这也称为间隙锁。 eg: 上面出现了间隙有 (3,7], (7,10], (10,21],(21,+∞] 的三个区间。 如果执行以下sql 那么其他事务就无法在 (7,21] 这个区间内插入或者修改任何数据。间隙锁会锁住 (7,10], (10,21] 这两个间隙。不过间隙锁只会在 可重复读事务隔离级别 下才会生效。 临键锁就是行锁和间隙锁的组合,也可以理解为一种特殊的间隙锁。通过临建锁可以解决幻读的问题。 每个数据行上的非唯一索引列上都会存在一把临键锁,当某个事务持有该数据行的临键锁时,会锁住一段左开右闭区间的数据 。 需要强调的一点是,InnoDB 中行级锁是基于索引实现的,临键锁只与非唯一索引列有关 ,在唯一索引列(包括主键列)上不存在临键锁。 上面的(7,21]就是临键锁。 参考: [1] https://www.jianshu.com/p/478bc84a7721MySQL锁总体结构
1. 悲观锁
2. 乐观锁
3. 读锁
4. 写锁
5. 表锁
LOCK TABLE 表名称 read(write);
LOCK TABLE user_table read;
LOCK TABLE user_table write;
SHOW OPEN TABLES;
UNLOCK TABLES;
6. 行锁
UPDATE user_table SET number = 2 WHERE name = 'fanone'
如果name没有加索引,那么可能会进行表锁。所以我们一般建议使用主键id作为更新数据的查询条件。
lock in share mode
命令来指定共享锁,使用
for update
命令来指定排他锁。
UPDATE user_table SET number = 2 WHERE name = 'fanone' LOCK IN SHARE MODE;
UPDATE user_table SET number = 2 WHERE name = 'fanone' FOR UPDATE;7. 页面锁
8. 间隙锁
SELECT * FROM user_user;
+----+-------+-------+
|id | name | sex |
+----+-------+-------+
| 1 |zhangsan| 1 |
| 2 |lisi | 2 |
| 3 |lisi2 | 2 |
| 7 |lisi3 | 2 |
| 10 |lisi4 | 2 |
| 21 |lisi5 | 2 |
+----+-------+-------+UPDATE user_user SET sex = 1 WHERE id > 8 AND id < 18;
9. 临键锁