数据库(2)数据库锁

这一段时间一直在学习关系型数据库,准备写一个小专题来总结一下这一段时间的学习结果。

一. 锁的分类

网上很多博客都是直接说了一连串的锁,什么悲观锁乐观锁,什么读写锁,什么排他锁共享锁。说的不仅语焉不详,而且分类紊乱,希望看到这篇文章能帮助你理清思路。

1.1 从锁的实现方式划分:乐观锁和悲观锁

从锁的实现方式来看,锁可以分为悲观锁和乐观锁。

  1. 乐观锁:以乐观的态度去预估并发操作中的数据冲突,不使用数据库提供的锁机制,而是通过数据库用户(程序员)添加某些字段来实现锁的机制,乐观锁不会真实的给数据上锁,所以开销较小。
  2. 悲观锁:悲观锁指的就是数据库管理系统提供的锁,之所以叫悲观锁,是因为这种锁无论是否有并发冲突,都会给数据上锁,因此开销相对来说较大。

乐观锁的一种实现方式:
使用版本号时,可以在数据初始化时指定一个版本号,每次对数据的更新操作都对版本号执行+1操作。并判断当前版本号是不是该数据的最新的版本号。

1.查询出商品信息
select (status,status,version) from t_goods where id=#{id}
2.根据商品信息生成订单
3.修改商品status为2
update t_goods set status=2,version=version+1
where id=#{id} and version=#{version};

可以看出,如果版本号在事物A进行中,发生了改变(事物B更新了数据),那么事物A就不能成功的修改数据,相当于加了一把锁。

但是乐观锁不适合高并发的情况,因为有可能几个事物同时读取了同一个版本号,然后同时进行了修改,这样就会出现数据不一致问题。所以数据库提供的悲观锁其实是必要的

1.2 从锁的加锁机制:共享锁和排他锁

从加锁的机制上,悲观锁分为共享锁和排他锁,共享锁又叫读锁,排他锁又叫写锁

共享锁和排他锁时数据库管理系统提供的数据锁,因此属于据悲观锁。

  1. 共享锁:共享锁常用于读取数据时,某用户(事物)对数据加共享锁以后,其他用户(事物)只能对该数据加共享锁,无法加排他锁。
  2. 排他锁:排他锁常用于写数据时,某用户(事物)对数据加排他锁以后,其他用户(事物)不能再对该数据加任何锁,只能等到解锁以后才可以继续加锁。

需要说明的是,在数据库管理系统中,所有的写操作都需要加排他锁,而读操作可以选择加共享锁,排他锁,也可以不加锁。因此一个加了共享锁的读操作,会导致其他事物无法修改这个读的数据。(这也就是serializable级别的实现方式)

在MylSQL中,如果SELECT操作加共享锁:

SELECT * FROM table_name LOCK IN SHARE MOED;

如果SELECT操作加排他锁:

SELECT * FROM table_name FOR UPDATE;

1.3 从锁的粒度上来说:行级锁和表级锁

首先要说明的是,无论是行级锁还是表级锁,都是数据库管理系统实现悲观锁的一种方式,也就是说共享锁和排他锁可以是行级也可以是表级。

  1. 表级锁:加锁时整个表都锁定,整个表的内容都无法被修改,直到解锁为止。这种锁因为锁的粒度较大,所以发生冲突的可能性较高,并发性低,但同时出现死锁的概率也相对较低。
  2. 行级锁:加锁时只有某行数据被锁定,而表内其他行不加锁,可以被修改和访问。这种锁发生冲突的概率较低,并发性较高,但是出现死锁的概率相对来说较高。

Mysql有些数据库引擎还提供了页级锁,但这些都是DBMS特异性的功能,在此就不表述。

二. 事物隔离等级和锁的关系

从理论上来说,事物的隔离等级都是通过数据库锁来实现的,但是又因为了MVCC机制出现,现代的数据库管理系统对于事物隔离等级的实现并不同。因此在这里只简单说明一下他们的关系。

1.1 写操作

对于数据库管理系统(MYSQL,SQLserver和Oracle)来说,所有的写操作(INSERT,UPDATE,DELETE),都是要加排他锁的,根据排他锁的性质我们可以得知,排他锁未解锁之前,不能再加排他锁,这样就保证了并发情况下的数据一致性。

因此在所有事物隔离等级中,写操作未提交之前,其他事物对于该数据的写操作都无法进行,因为该数据已经锁定。

要多说一点的说,数据库管理系统对于写操作时锁的粒度是有不同的,以Mysql来说,对于InnoDB引擎,对于索引的数据进行写操作,会使用行级锁,但是如果这个数据没有索引,还是会对全表加锁。

1.2 读操作

根据前面我所说的,事物其实主要针对数据库的写操作,而Mysql中事物写操作加锁的情况,仅仅出现在serilizable等级下,这种事物隔离等级下,读操作加共享锁写操作加排他锁。

其他隔离等级下的SELECT操作是不会加锁的,因为Mysql有一种读快照(snapshot read)的机制,也就是说其实普通的读操作不会真正读取到数据库中的内容,而是读取了一个版本的快照,只有加锁读(共享锁还有排他锁都可以),才是读取数据库当前存储的内容。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值