Java教程

数据库各种锁详解

本文主要是介绍数据库各种锁详解,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

文章目录

  • 排他锁
  • 共享锁
  • 更新锁
  • 意向锁
  • 锁的粒度
  • 数据库自动加锁
  • 手动加锁
  • 各种锁之间的兼容问题

排他锁

Exclusive Locks,英译:排他锁,简称 X 锁,又称为写锁或独占锁。排他锁分为表级排他锁和行级排他锁。

如果事务 T1 对数据行对象 A 加上了行级排他锁,那么事务 T1 可以对数据行对象 A 进行读取和更新操作,其他事务则只能对数据行对象 A 进行读取操作,而不能进行更新操作,并且其它事务不能再往数据行对象 A 上加任何类型的锁,直到 T1 释放了行级排他锁。

MySQL 的 InnoDB 引擎默认的修改数据语句 update、delete、insert 都会自动给涉及到的数据加上行级排他锁,而 select 语句默认不会加任何锁,如果查询的时候要加行级排他锁可以使用 select ...for update 语句,加行级共享锁可以使用 select ... lock in share mode 语句。

所以加过行级排他锁的数据行其他事务是不能通过 for updatelock in share mode 方式查询数据,但可以直接通过 select ...from... 查询数据,因为普通查询没有加任何锁。

事务 T1 如果对某张表加了表级排他锁,表示事务 T1 可以对该表中的所有记录进行查询和修改,而其它事务只能查询不能修改。并且其它事务不能再往这张表加任何类型的表级锁,也不能给表中的数据行加任何的行级锁。

共享锁

Shared Lock,英译:共享锁,简称 S 锁,又称读锁。共享锁分为表级共享锁和行级共享锁。

顾名思义,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改。即共享锁不阻塞其他事务的读操作,但阻塞写操作。

当事务 T1 为数据行对象 A 加上行级共享锁后,事务 T1 可以对数据行对象 A 进行读操作,但不能进行写操作,并且事务 T2 可以再次对数据行对象 A 加行级共享锁,但是不能加行级排他锁,也不能加表级排他锁。大家都可以正常地读取数据行对象 A,在数据行对象 A 上的所有共享锁释放之前,任何事务不可以对数据行对象 A 进行写操作。

数据行对象 A 可以共存多个行级共享锁,这被称为行级共享锁兼容。加了行级共享锁的数据行对象 A 不能再加行级排他锁,所以行级共享锁和行级排他锁是不兼容的。

当事务 T1 为某张表添加了表级共享锁,表示事务 T1 可以查看表中的所有记录,但是不能修改,而且其它事务也只能查看数据不能修改数据。但是其它事务可以再往这张表添加表级共享锁和意向共享锁,其它事务也可以往这张表中的记录添加行级共享锁;但是其它事务不能再往这张表添加表级的排他锁,也不能添加意向排他锁,其它事务也不能往这张表中的记录添加行级排他锁。

更新锁

Update Lock,英译:更新锁,简称 U 锁。更新锁只有行级的更新锁。

当事务 T1 给数据行对象 A 加上更新锁后,代表数据行对象 A 将在稍后被更新。更新锁允许其他事务在事务 T1 操作更新之前读取数据行对象 A,但不可以修改。其他事务修改数据行对象 A 之前会先往数据行对象 A 加行级排他锁,但是发现数据行对象 A 已存在 U 锁,所以加行级排他锁失败,只能等待 U 锁释放。

更新锁与行级共享锁兼容;更新锁与表级共享锁不兼容;更新锁与更新锁互不兼容;更新锁与行级排他锁不兼容,更新锁与表级排他锁不兼容。

因此数据行对象 A 不可以再添加更新锁,但是可以添加行级共享锁,但是添加行级共享锁的意义不大,因为事务 T1 找到需要更新的数据时,更新锁直接转为行级排他锁,开始更新数据,不需要等待其他事务释放行级共享锁,所以在有更新锁的数据资源上加行级共享锁就毫无意义了。

意向锁

在数据行对象上加 U、X、S 之前都会先为表或者页加意向锁。意向锁是一种表级锁,表明“某个事务对表中的记录加了某种锁或准备加某种锁。

常用的意向锁有三种:
1.Intent Share Lock,英译:意向共享锁,简称 IS 锁

事务 T1 在给数据行对象添加行级 S 锁前,要先获得 IS 锁。如果表被加了 IS 锁,说明某个事务对这个表中的某些数据行加了行级 S 锁。当其它事务想要在这个表上加一个表级排他锁时,发现这个表已经加了意向共享锁,那么就不可以加表级的排他锁了。

2.Intent Exclusive Lock,英译:意向排他锁,简称 IX 锁

事务在请求行级 X 锁前,要先获得 IX 锁
事务 T1 修改 user 表的数据行对象 A,会给数据行对象 A 上一把行级的排他锁,但是在给数据行对象 A 上行级排他锁前会先给 user 表上一把意向排他锁,这时事务 T2 要给 user 表上一个表级的排他锁就会被阻塞。

3.Share Intent Exclusive Lock,英译:共享意向排他锁,简称 SIX 锁

共享意向排他锁的意思是,某事务要读取整个表,并更新其中的某些数据。

我质疑存在这种锁,在网络上找不到关于共享意向排它锁的任何资料。

锁的粒度

锁的粒度指的是锁生效的范围,即行锁、页锁、表锁等。锁的粒度一般由数据库自主管理,不同的事务隔离级别,数据库会有不同的加锁策略(比如加什么类型的锁,加什么粒度的锁)。

数据库自动加锁

其实锁在大多数情况下都是数据库自动加的,数据库会根据隔离级别的不同,按照策略来加锁。

比如这么一条语句:

mysql> update student set class = '高二(3)班'; 

通过性能分析工具 Profiler 跟踪 sql 发现,数据库系统会逐行先获取 U 锁,然后转为 X 锁,对数据行进行更新,更新完后并不释放 X 锁,接着继续获取下一行的 U 锁,转为 X 锁,更新数据…,不断重复以上流程,直到全部数据行更新完成后,再逐行释放掉所有的 X 锁。

而如果加上 where 条件,如:

mysql> update student set class = '高二(3)班' where name = 'liudehua';

如果字段 name 没有索引,则逐行获取 U 锁,如果符合条件,转为 X 锁,执行更新,不释放 X 锁;如果不符合条件,释放 U 锁。

如果有索引的话,则不需要全表扫描逐行处理,而是直接定位到要更新的数据行,然后逐行加上 X 锁,接着执行更新,更新后不释放 X 锁,直到所有定位到的数据行更新完成后,再逐行释放 X 锁。

手动加锁

手动加行级排他锁,如下所示:

mysql> begin; -- 开始事务
Query OK, 0 rows affected (0.00 sec)

mysql> select * from account where id = 5 for update; -- 查询到的数据行全部加上行级的排他锁
+----+----------+---------+
| id | NAME     | balance |
+----+----------+---------+
|  5 | zhangsan | 1000.00 |
+----+----------+---------+
1 row in set (0.00 sec)

手动加行级共享锁,如下所示:

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from account where id = 5 lock in share mode;
+----+----------+---------+
| id | NAME     | balance |
+----+----------+---------+
|  5 | zhangsan |    0.00 |
+----+----------+---------+
1 row in set (0.01 sec)

手动给表加表级的排他锁,如下所示:

mysql> lock tables account write; -- 给表account加排他锁,即写锁
Query OK, 0 rows affected (0.00 sec)

注:
1.会话 S1 对表 account 加上表级排他锁后,其它会话不能对该表 account 进行查询和修改操作。
2.会话 S1 对表 account 加上任何表级锁后,该会话不能对其它非锁表进行任何的操作。

手动给表加表级的共享锁,如下所示:

mysql> lock tables account read; -- 给表account 加共享锁,即读锁
Query OK, 0 rows affected (0.00 sec)

给多个表加表级锁,如下所示:

mysql> lock table user write,account write;
Query OK, 0 rows affected (0.00 sec)

手动解锁,如下所示:

mysql> unlock tables;

各种锁之间的兼容问题

-行级 S行级 U行级 X表级 S表级 XISIX
行级 S兼容加了 S 锁不能再加 U 锁,但是先加 U 锁,可以再加 S 锁不兼容兼容不兼容兼容兼容
行级 U加了 S 锁不能再加 U 锁,但是先加 U 锁,可以再加 S 锁不兼容不兼容不兼容不兼容兼容兼容
行级 X不兼容不兼容不兼容不兼容不兼容兼容兼容
表级 S兼容不兼容不兼容兼容不兼容兼容不兼容
表级 X不兼容不兼容不兼容不兼容不兼容不兼容不兼容
IS兼容不兼容不兼容兼容不兼容兼容兼容
IX兼容兼容兼容不兼容不兼容兼容兼容
这篇关于数据库各种锁详解的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!