侧边栏壁纸
博主头像
落叶人生博主等级

走进秋风,寻找秋天的落叶

  • 累计撰写 130562 篇文章
  • 累计创建 28 个标签
  • 累计收到 9 条评论
标签搜索

目 录CONTENT

文章目录

mysql-【锁】总结

2022-06-13 星期一 / 0 评论 / 0 点赞 / 212 阅读 / 3669 字

读锁与写锁X锁S锁X锁冲突冲突S锁冲突不冲突读锁:当前事务给某些数据加了读锁,允许其他事务加读锁但不允许加写锁。也可以称之为共享锁、Shared Locks、S锁示例select * from tab

读锁与写锁

X锁S锁
X锁冲突冲突
S锁冲突不冲突

读锁:当前事务给某些数据加了读锁,允许其他事务加读锁但不允许加写锁。也可以称之为共享锁、Shared Locks、S锁

示例

select * from table_a lock in share mode

使用场景:读出数据后其他事务不能修改,但自己也不一定能修改,因为其他事务也可以加读锁。主要用来保证数据在本事务内值不会变。但实际开发中用得比较少。

写锁:当前事务如果加了写锁,其他事务若加锁会阻塞。也可以称之为排他锁、Exclusice Locks、X锁

示例

select * from table_a for update 以及 DELETE/UPDATE/INSERT(插入后未提交的数据也会加写锁)

使用场景:只有本事务才可以修改这些数据,其他事务加锁会阻塞。一般开发过程中大部分接触到的锁都是写锁。

行锁与表锁

行锁:只有InnoDB里才会有。

行锁又分为:

  • LOCK_REC_NOT_GAP:单个行记录上的锁。
  • LOCK_GAP:间隙锁,锁定一个范围,但不包括记录本身。什么意思呢?比如查询一条ID为7的数据,间隙锁是给ID=7这条数据上下记录间的间隙给锁定,但记录本身不上锁。就如MVCC是解决可重复读的问题一样,间隙锁是解决幻读的问题,即同一事务内,数据总数不变。
  • LOCK_ORDINARY:同上,也是间隙锁,只是锁定范围包括记录本身。我们一般所说的间隙锁就是这个。

示例:

select * from table_a where a = 1 for update

  • 事务隔离级别为读提交时会对查询出的所有每条数据加行锁(单个行记录上锁),但此时其他事务可以针对这个数据范围insert造成幻读。

  • 当事务隔离级别为可重复读时(mysql默认的事务隔离级别)如果走索引,mysql通过索引知道数据的范围,会对查询出的数据范围间隙及数据本身加锁,其他事务针对这个数据范围写操作都会阻塞,包括insert在这个间隙范围内的操作,以避免幻读。

  • 但如果sql语句不走索引全表扫描,此时mysql并不知道数据范围,mysql只能对所有的数据和间隙上锁以避免幻读。

表锁

表锁在InnoDB中应用很少,写操作是不会加表级别的锁。

而DDL语句也会发生阻塞,这个过程是通过使用元数据锁(Metadata Locks,MDL)来实现的,并不是表级别的锁。但是可以用过以下方式加表锁

  • LOCK TABLES t1 READ
  • LOCK TABLES t1 WRITE

但是不建议使用,因为InnoDB的优点就是行锁,表锁性能差。

总结

  • mysql默认事务隔离级别是可重复读,所以需要重点关注的概念:写锁、行锁、间隙锁。
  • 读锁与写锁是对锁功能的分类,而行锁与表锁是对锁范围的一个分类。
.
.

广告 广告

评论区