Mysql共享锁、排他锁

Mysql共享锁、排他锁

名词及含义

  • 表级锁(锁定整个表)
  • 页级锁(锁定一页)
  • 行级锁(锁定一行)
  • 共享锁(S锁,MyISAM 叫做读锁)
  • 排他锁(X锁,MyISAM 叫做写锁)
  • 间隙锁(NEXT-KEY锁)
  • 悲观锁(抽象性,不真实存在这个锁)
  • 乐观锁(抽象性,不真实存在这个锁)

InnoDB与MyISAM

我之前专程写了Mysql中MyISAM和InnoDB区别Mysql存储引擎

这里主要写一些影响锁相关的内容

Mysql 在5.5之前默认使用 MyISAM 存储引擎,之后使用 InnoDB 。查看当前存储引擎:

show variables like '%storage_engine%';

MyISAM 操作数据都是使用的表锁,你更新一条记录就要锁整个表,导致性能较低,并发不高。当然同时它也不会存在死锁问题。

而 InnoDB 与 MyISAM 的最大不同有两点:一是 InnoDB 支持事务;二是 InnoDB 采用了行级锁。也就是你需要修改哪行,就可以只锁定哪行。

在 Mysql 中,行级锁并不是直接锁记录,而是锁索引。索引分为主键索引和非主键索引两种,如果一条sql 语句操作了主键索引,Mysql 就会锁定这条主键索引;如果一条语句操作了非主键索引,MySQL会先锁定该非主键索引,再锁定相关的主键索引。

InnoDB 行锁是通过给索引项加锁实现的,如果没有索引,InnoDB 会通过隐藏的聚簇索引来对记录加锁。也就是说:如果不通过索引条件检索数据,那么InnoDB将对表中所有数据加锁,实际效果跟表锁一样。因为没有了索引,找到某一条记录就得扫描全表,要扫描全表,就得锁定表。

共享锁与排他锁

数据库的增删改操作默认都会加排他锁,而查询不会加任何锁。

mysql InnoDB引擎默认的修改数据语句,update,delete,insert都会自动给涉及到的数据加上排他锁select语句默认不会加任何锁类型,如果加排他锁可以使用select …for update语句,加共享锁可以使用select … lock in share mode语句。所以加过排他锁的数据行在其他事务种是不能修改数据的,也不能通过for update和lock in share mode锁的方式查询数据,但可以直接通过select …from…查询数据,因为普通查询没有任何锁机制。

共享锁

对某一资源加共享锁,自身可以读该资源,其他人也可以读该资源(也可以再继续加共享锁,即 共享锁可多个共存),但无法修改。要想修改就必须等所有共享锁都释放完之后。语法为:

select * from table lock in share mode

排他锁

对某一资源加排他锁,自身可以进行增删改查,其他人无法进行任何操作。语法为:

select * from table for update

排他锁和共享锁 只会对加锁的sql语句进行阻塞

例如A事务:

start TRANSACTION;
select * from table_name where id = 1 for UPDATE;

B事务

# 不会阻塞 直接查出答案
select * from table_name where id = 1

C事务

# 阻塞 等待事务A提交
select * from table_name where id = 1 for UPDATE;

间隙锁

什么叫间隙锁

当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁;对于键值在条件范围内但不存在的记录,叫做“间隙(GAP)”,InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁(NEXT-KEY)锁。

间隙锁的产生

上面的文字很抽象,现在举个栗子,介绍间隙锁是怎么产生的:

假设有以下表t_student:

idnamesexaddress
1a0cq
3b1cq
4c0cq
5d1cq
6e0cq

这个时候我们发出一条这样的加锁sql语句:

start TRANSACTION;
select id,name from t_student where id > 0 and id < 5 for update;

这时候,我们命中的数据为以下加粗部分:

idnamesexaddress
1a0cq
3b1cq
4c0cq
5d1cq
6e0cq

细心的朋友可能就会发现,这里缺少了条id为2的记录,我们的重点就在这里。

select ... for update这条语句,是会对数据记录加锁的,这里因为命中了索引,加的是行锁。从数据记录来看,这里排它锁锁住数据是id为1、3和4的这3条数据。

但是,看看前面我们的介绍——对于键值在条件范围内但不存在的记录,叫做“间隙(GAP)”,InnoDB也会对这个“间隙”加锁。

好了,我们这里,键值在条件范围但是不存在的记录,就是id为2的记录,这里会对id为2数据加上间隙锁。假设这时候如果有id=2的记录insert进来了,是要等到这个事务结束以后才会执行的

间隙锁的作用

总的来说,有2个作用:防止幻读和防止数据误删/改

因为加锁了,所以其他(删/改/增)都会被阻塞

使用间隙锁的隐患

最大的隐患就是性能问题

如果间隙锁出现死锁的情况下,会更隐晦,更难定位

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值