目录标题
前言
在 MySQL 数据库中,提供锁机制这个功能的是存储引擎,如果需要使用行锁就必须使用支持行锁的存储引擎。在 MySQL 数据库中,MyISAM 存储引擎是不支持行级锁的,支持行锁的是 InnoDB 存储引擎,这也是 MySQL 数据库后来选择 InnoDB 存储引擎为默认存储引擎的原因之一。
行级锁的功能是跟表级锁类似,都是用来锁定数据的,用来防止并发导致数据修改失败这种情况的出现。所不同的是表锁是锁定整个表的数据,而行级锁是操作一行、锁定一行,并且行级锁也是 MySQL 中粒度最小的锁。
当操作某个数据表中的数据使用表级锁时,整个数据表中所有的数据都会被锁定而无法操作,也就是同一时间只能有一个修改操作,这是非常影响数据库并发的,不适合访问量大的场景。而行级锁是操作一行、锁定一行,所以在最大程度上减少了数据表中多个操作之间的冲突,进而提升了数据库数据更新的并发。
行级锁
行级锁就是将修改一行、锁住一行。但这里有一点我们需要注意:行级锁是产生于一个事务之中的,当事务提交或者回滚之后,行级锁立即自动释放。
在 MySQL 数据库中行级锁主要有两种,分别是:共享锁与排他锁。
1. 共享锁(Shared Lock)
共享锁又称为读锁,也可以简称为:S 锁。添加共享锁的语句为:lock in share mode。当多个事务同一时间修改同一条数据时,共享锁只允许其中的一个事务修改数据,读数据则不限制。
通常情况下,共享锁的使用场景是保证数据库中数据与数据之间的关系。举个例子:我们在购物时,总是会让我们添加地址;在填写地址之时,首先会让我们选择省份,其次是市,最后是详细的地址。在这个场景中,如果我们需要添加浦东新区的话,就意味着上海市这个上级选项必须存在。假设,我们添加浦东新区时,恰好其他人把上海市删除;那此时,我们添加的浦东新区就失去了它的意义。
为了防止这个情况的发生,我们最好添加一个锁机制,这个锁机制既不影响数据库的正常读,又能保证数据关系一致。在这种场景下,我们正好用到共享锁。
下面我们利用上面填写地址的例子,来描述一下共享锁的使用场景。
步骤 1,在事务一中开启一个共享锁,在事务二中测试共享锁是否影响查询:
-- 在事务二中查询该条数据,发现添加了共享锁的数据仍然可以正常查询。
mysql> select * from province where id = 1;
+----+-----------+
| id | name |
+----+-----------+
| 1 | 上海市 |
+----+-----------+
1 row in set (0.08 sec)
可以看出,增加了共享锁之后,其他事务中该条数据是可以正常查询的。
步骤 2,当加上共享锁之后,添加浦东新区,同时删除上海市:
在事务1中增加共享锁,同时增加一条数据
<