关于java:MySQL的锁这么多不知从何学起看完这篇文章就够了

26次阅读

共计 1502 个字符,预计需要花费 4 分钟才能阅读完成。

MySQL 有两个外围的知识点,索引和锁。前几篇文章曾经具体解说了 MySQL 索引实现机制,明天再一起学习一下 MySQL 的锁。

1 为什么要加锁?

当多个事务并发操作同一批数据的时候,如果不加锁,就无奈保障事务的隔离性,最初导致数据错乱。

加锁是为了保障并发操作下数据的正确性。

2 锁的分类有哪些?

按锁的粒度可分为:表锁、页面锁、行锁、记录锁、间隙锁、临键锁

按锁的属性可分为:共享锁、排它锁

按加锁机制可分为:乐观锁、乐观锁

上面顺次介绍一下这几种锁:

表锁:

MyISAM 和 InnoDB 引擎均反对表锁。

长处:开销小,加锁快,不会呈现死锁。

毛病:锁定力度大,产生锁抵触概率高,并发度最低。

加锁形式:

# 对 user 表加读锁
lock table user read;
# 同时对 user 表加读锁,对 order 表加写锁
lock tables user read, order write;

什么状况下须要用到表锁?

  1. 当须要更新表中的大部分数据
  2. 事务波及到多张表,业务逻辑简单,加表锁能够防止死锁。

页面锁:

长处:开销和加锁速度介于表锁和行锁之间。

毛病:会呈现死锁,锁定粒度介于表锁和行锁之间,并发度个别。

目前只有 BDB 引擎反对页面锁,利用场景较少。

行锁:

只有 InnoDB 引擎反对行锁,另外锁是加在索引下面的。

长处:开销大,加锁慢;会呈现死锁。

毛病:锁定粒度小,产生锁抵触的概率低,并发度高。

另外记录锁、间隙锁、临键锁均属于行锁。

记录锁(Record Locks):

即对某条记录加锁。

# 对 id= 1 的用户加锁
update user set age=age+1 where id=1;

间隙锁(Gap Locks):

即对某个范畴加锁,然而不蕴含范畴的临界数据。

# 对 id 大于 1 并且小于 10 的用户加锁
update user set age=age+1 where id>1 and id<10;

下面 SQL 的加锁范畴是(1,10)。

临键锁(Next-Key Locks):

由记录锁和间隙锁组成,既蕴含记录自身又蕴含范畴,左开右闭区间。

# 对 id 大于 1 并且小于等于 10 的用户加锁
update user set age=age+1 where id>1 and id<=10;

共享锁(又称读锁、S 锁):

作用:避免其余事务批改以后数据。

加锁形式:

在 select 语句开端加上 lock in share mode 关键字。

# 对 id= 1 的用户加读锁
select * from user where id=1 lock in share mode;

排他锁(又称写锁、X 锁):

作用:避免其余事务读取或者更新以后数据。

加锁形式:

在 select 语句开端加上 for update 关键字。

# 对 id= 1 的用户加写锁
select * from user where id=1 for update;

乐观锁:

总是假如他人不会批改以后数据,所以每次读取数据的时候都不会加锁,只是在更新数据的时候通过 version 判断他人是否批改过数据,Java 的 atomic 包下的类就是应用乐观锁(CAS)实现的。

实用于读多写少的场景。

加锁形式:

  1. 读取 version

    select id,name,age,version from user id=1;
  2. 更新数据,判断 version 是否批改过。

    update user set age=age+1 where id=1 and version=1;

乐观锁:

总是假如他人会批改以后数据,所以每次读取的时候,总是加锁。

实用于写多读少的场景。

加锁形式:

# 加读锁
select * from user where id=1 lock in share mode;
# 加写锁
select * from user where id=1 for update;

本文知识点总结:

文章继续更新,能够微信搜一搜「一灯架构」第一工夫浏览更多技术干货。

正文完
 0