面试专题:简述MySQL数据库锁的种类

2024-01-29 11:50:58 浏览数 (1)

前言

数据库通过锁机制来解决并发场景-共享锁(读锁)和排他锁(写锁)。读锁是不阻塞的,多个客户端可以在同一时刻读取同一个资源。写锁是排他的,并且会阻塞其他的读锁和写锁。

简单提下乐观锁和悲观锁。

  • 乐观锁,通常用于数据竞争不激烈的场景,多读少写,通过版本号和时间戳实现。
  • 悲观锁,通常用于数据竞争激烈的场景,每次操作都会锁定数据。

要锁定数据需要一定的锁策略来配合。

  • 表锁,锁定整张表,开销最小,但是会加剧锁竞争。
  • 行锁,锁定行级别,开销最大,但是可以最大程度的支持并发。

但是MySql的存储引擎的真实实现不是简单的行级锁,一般都是实现了多版本并发控制(MVCC)。MVCC是行级锁的变种,多数情况下避免了加锁操作,开销更低。MVCC是通过保存数据的某个时间点快照实现的。

锁的种类

接下来按照锁的分类,介绍三种锁的使用方式的注意点。

共享锁(行锁)

又名读锁,自己、其他人都可以读该资源,但是其他人不可以修改,要修改必须等共享锁释放

加锁:select * from table lock in share mode

释放:commit、rollback

排他锁(行锁,写锁)

自身增删查改,其他人无法任何操作,不能与其他锁并存

加锁:

         自动:事务进行中的DML操作自动加锁,其他操作:修改删除加锁都不行

         手动:  select * from table for update

       释放:commit、rollback

注意:

for update 在java代码必须加在Transation注解上方法才生效。如果查询条件用了索引/主键,那么select ..... for update就会进行行锁。如果是普通字段(没有索引/主键),那么select ..... for update就会进行锁表。但是如果select没有数据为空情况,会怎样呢?其实也会,变成锁表,这时候,如果有insert或者Update操作,就会出现死锁情况。所以for Update的查询结果,应该作为判空处理,而不是判断非空。

意向锁(表锁)

全表操作加表锁,比如加普调工资,这时候就不需要其他人来读取操作表,如果要加表锁前,每行去检查是否加锁(排他锁,共享锁)效率很差。所以引入一个意向锁,如果表中有某行加了共享锁或者排他锁,就加响应的意向锁,当要对这个表加表锁是就检查是否有意向锁。

所以意向锁是通知有没有数据表锁定了,提供叫表锁的效率。

引申问题:建表都要建索引主键索引?主键索引有什么作用

  1. 提升查询效率
  2. 如果没有建主键或者唯一索引

一个事务,本来默认是行锁排他锁,由于没有唯一索引,会自动升级为表锁(MySQL底层自己决定),导致其他事务无法修改其他行

代码语言:sql复制
update *** where sex = 0

另一个事务执行,以下语句不成功

代码语言:sql复制
update *** where sex = 1

总结

MySQL数据库锁是确保数据完整性和并发性能的关键组件。理解和掌握不同类型的锁以及其工作原理是优化数据库性能和避免常见问题的关键,在实际项目中也可以根据数据库锁的分类进行调优,熟悉数据库锁的种类,在面试中回答也能够游刃有余。

我正在参与2024腾讯技术创作特训营第五期有奖征文,快来和我瓜分大奖!

0 人点赞