美文网首页
mysql进阶-行级锁、表级锁、乐观锁、悲观锁

mysql进阶-行级锁、表级锁、乐观锁、悲观锁

作者: 木语沉心 | 来源:发表于2020-11-18 11:30 被阅读0次

从应用的角度来看数据库锁可分为悲观锁、乐观锁
从数据库(InnoDB)的角度看,数据库锁可以分为行级锁和表级锁

1.1 什么是行级锁

InnoDB 存储引擎默认情况下,使用行级锁。行级锁是 MySQL 中锁定粒度最细的一种锁,它锁住的是行记录。行级锁可以大大减少数据库操作的冲突,但是加锁的开销也是非常大的。它具有如下特点:

  • 由于开销比较大,加锁会很慢
  • 锁定粒度小,所以锁冲突的概率低,并发度高
  • 可能会出现死锁

1.2 什么是表级锁

表级锁是 MySQL 中锁定粒度最大的一种锁,它会锁住整张表。由于锁定粒度很大,它的实现会简单许多,资源消耗也会很低,大部分的存储引擎都支持表级锁,它具有如下特点:

  • 由于开销比较小,加锁会很快
  • 锁定粒度大,所以锁冲突的概率高,并发度低
  • 不会出现死锁

1.3 MySQL 如何选择行级锁与表级锁

InnoDB 是否使用行级锁是通过索引来确定的,没有通过只能全表扫描使用的是表级锁

在有些特殊情况下是不成立的。例如,对于数据量很少的表,MySQL 会认为全表扫描更快,此时,即使使用索引字段查询,InnoDB 也会使用表锁,而不是行锁。

2.1 什么是悲观锁

在应用层面上以最坏的角度去对待并发的数据控制,认为共享数据被并发修改的可能性较高,在修改之前先去加锁 效率上,

缺点:处理加锁的过程会让数据库产生额外的开销,降低并发度,同时,还可能会有死锁的可能。

悲观锁的实现,依赖于数据库提供的锁机制(行级锁、表级锁)。它的工作流程可以总结如下:!
对数据操作之前,尝试获取锁
获取锁成功,对数据进行修改、提交事务,最后释放锁
获取锁失败,则锁正在被占用,等待或抛出异常


image

2.2 什么是乐观锁

相对悲观锁而言的,乐观锁假设数据一般情况下不会造成冲突,所以在数据进行最后提交更新的时候,才会正式对数据的冲突与否进行检测。
乐观锁并不是真正意义上的 “锁”,所以,不会使用到数据库的锁机制。实现由SQL执行先后状态一致进行判断 不会产生死锁的情况。


image

3.1 使用悲观锁

使用悲观锁,必须关闭 MySQL 的自动提交(MySQL 默认使用自动提交模式)
使用方式是:SELECT … FOR UPDATE。

-- 关闭自动提交
mysql> SET autocommit = off;

-- 校验自动提交是否关闭
mysql> SHOW VARIABLES LIKE 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | OFF   |
+---------------+-------+

-- “会话 A” 通过悲观锁语法锁住 id 为 1 的记录
mysql> SELECT * FROM worker WHERE id = 1 FOR UPDATE;
+----+------+------+--------+
| id | type | name | salary |
+----+------+------+--------+
|  1 | A    | tom  |   1800 |
+----+------+------+--------+

-- “会话 B” 也通过悲观锁语法锁住 id 为 1 的记录
-- 由于锁被 “会话 A” 占据,长时间获取不到锁,报了锁超时错误
mysql> SELECT * FROM worker WHERE id = 1 FOR UPDATE;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

-- “会话 A” 更新记录
mysql> UPDATE worker SET salary = 2000 WHERE id = 1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

-- “会话 A” 提交事务
mysql> commit;
Query OK, 0 rows affected (0.02 sec)

-- “会话 B” 在 “会话 A” 提交事务之后,获取锁成功(观察 SQL 语句执行耗时)
mysql> SELECT * FROM worker WHERE id = 1 FOR UPDATE;
+----+------+------+--------+
| id | type | name | salary |
+----+------+------+--------+
|  1 | A    | tom  |   2000 |
+----+------+------+--------+
1 row in set (25.13 sec)

SELECT … FOR UPDATE 只允许一个事务获取到锁,其他的事务只能等待或者超时

3.2 使用乐观锁

实现:判断 数据查询修改前后状态记录字段是否一致 (比如status,timestamp)

-- 查询需要修改的记录,并把当前 salary 的值作为预定义的比对条件
mysql> SELECT * FROM worker WHERE id = 1;
+----+------+------+--------+
| id | type | name | salary |
+----+------+------+--------+
|  1 | A    | tom  |   2000 |
+----+------+------+--------+
1 row in set (0.00 sec)

-- 更新记录 salary 的值,并比对之前预定义的条件是否一致
mysql> UPDATE worker SET salary = 1800 WHERE id = 1 AND salary = 2000;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

-- 比对一致,更新成功
mysql> SELECT * FROM worker WHERE id = 1;
+----+------+------+--------+
| id | type | name | salary |
+----+------+------+--------+
|  1 | A    | tom  |   1800 |
+----+------+------+--------+
1 row in set (0.00 sec)

4.1 悲观锁、乐观锁的特性及优缺点

悲观锁是依赖于数据库(存储引擎)

  • 优点:利用锁机制保证了数据的顺序执行,不需要自己控制,加锁、释放完全由数据库代劳
  • 缺点:一旦一个事务获取了锁,其他的事务必须等待,势必会影响系统的吞吐量

乐观锁不是真正的加锁,对其他事务友好(不会造成死锁)

  • 优点:由于不需要加锁,其他的事务可以同时操作数据,相比于悲观锁,系统吞吐量会提高
  • 缺点:需要自行控制,如果并发度较高,失败重试的情况会成为系统瓶颈

4.2 悲观锁、乐观锁的适用场景

  • 悲观锁的适用场景:写入操作比较频繁的场景,如果有大量的读取操作,每次读取都需要加锁,会增加锁开销,降低系统的吞吐量
  • 乐观锁的适用场景:读取操作比较频繁的场景,如果有大量的写入操作,冲突的可能性会剧增,降低系统的吞吐量

相关文章

  • mysql进阶-行级锁、表级锁、乐观锁、悲观锁

    从应用的角度来看数据库锁可分为悲观锁、乐观锁从数据库(InnoDB)的角度看,数据库锁可以分为行级锁和表级锁 1....

  • rails中乐观锁和悲观锁的使用

    MySQL乐观锁和悲观锁的介绍可以参考之前的一篇文章MySQL中的锁(行锁,表锁,乐观锁,悲观锁,共享锁,排他锁)...

  • mysql锁

    mysql锁 性能:乐观锁,悲观锁 操作类型:读锁,写锁,都属于悲观锁 操作粒度:行锁,表锁 乐观锁:一种思想,通...

  • mysql锁记录

    mysql锁 性能:乐观锁,悲观锁 操作类型:读锁,写锁,都属于悲观锁 操作粒度:行锁,表锁 乐观锁:一种思想,通...

  • 数据库相关问题与解答

    收集常见数据库问题 锁机制介绍:行锁、表锁、排他锁、共享锁,悲观锁、乐观锁。行级锁:开销大,加锁慢;会出现死锁;锁...

  • mysql 锁

    MySQL学习之——锁(行锁、表锁、页锁、乐观锁、悲观锁等)https://crossoverjie.top/ht...

  • MySQL05

    数据库高级对象,锁,权限管理 视图 索引 触发器 存储过程 悲观锁与乐观锁 行级锁、表级锁、页锁 数据库权限管理 ...

  • MySQL的锁机制

    锁的类型 MySQL的锁分为:行级锁、表级锁、页级锁 MyISAM 和 Memory 存储引擎使用的是表级锁 In...

  • Mysql的锁机制

    根据加锁的粒度区分 全局锁 表级锁 行锁记录锁间隙锁临键锁 根据加锁的场景 乐观锁 悲观锁 全局锁 锁对象是:整个...

  • MS汇总

    数据库相关[MS-关于锁(乐观锁,悲观锁,行锁、表锁,共享锁,排他锁)Mysql索引优化Mysql查询优化Mysq...

网友评论

      本文标题:mysql进阶-行级锁、表级锁、乐观锁、悲观锁

      本文链接:https://www.haomeiwen.com/subject/euaqiktx.html