表锁,行锁,排他锁,共享锁,悲观锁和乐观锁

行锁:

mysql,innodb,使用的是行锁.每次插入/更新时会自动加锁.

mysql的行锁是基于索引加载的

行锁的特征:锁冲突概率低,并发性高,但是会有死锁的情况出现。

表锁:

myisam,使用的时表锁

表锁就是一锁锁一整张表,在表被锁定期间,其他事务不能对该表进行操作,必须等当前表的锁被释放后才能进行操作

特征:锁表快,性能低

排他锁:

如果事务 T1对数据对象 O1加上了排他锁,那么在整个加锁期间,只允许事务 T1对 O1进行读取和更新操作,其他任何事务都不能再对这个数据对象进行任何类型的操作——直到T1释放了排他锁。

共享锁:

共享锁又称为读锁,简称S锁,顾名思义,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改。

注意:

update,delete,insert都会自动给涉及到的数据加上排他锁,select语句默认不会加任何锁类型,

如果加排他锁可以使用select ...for update语句,加共享锁可以使用select ... lock in share mode语句。

https://mp.weixin.qq.com/s?src=11&timestamp=1611682898&ver=2852&signature=SQIz50Xb2bHcPmxLV0xuHOUkLjwqsNYNVl9PFiXnYWKW6Oho*bnwv2z0pUZpP4ZaaVjT8kvN6wyHLjSqhoHcnZCi1C3Vkk1uWGqlkHXKo4hqFyvE1MAOH-M-m9bXrTGA&new=1

悲观锁(Pessimistic Lock)

顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。

乐观锁(Optimistic Lock)

顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。

像乐观锁适用于写比较少的情况下,即冲突真的很少发生的时候,这样可以省去锁的开销,加大了系统的整个吞吐量。

但如果经常产生冲突,上层应用会不断的进行重试,这样反倒是降低了性能,所以这种情况下用悲观锁就比较合适。

场景:

下面这个假设的实际场景可以比较清楚的帮助我们理解这个问题:
假设当当网上用户下单买了本书,这时数据库中有条订单号为001的订单,其中有个status字段是’有效’,表示该订单是有效的;

后台管理人员查询到这条001的订单,并且看到状态是有效的
用户发现下单的时候下错了,于是撤销订单,假设运行这样一条SQL: update order_table set status = ‘取消’ where order_id = 001;

后台管理人员由于在b这步看到状态有效的,这时,虽然用户在c这步已经撤销了订单,可是管理人员并未刷新界面,看到的订单状态还是有效的,于是点击”发货”按钮,将该订单发到物流部门,同时运行类似如下SQL,将订单状态改成已发货:update order_table set status = ‘已发货’ where order_id = 001

实现:

https://mp.weixin.qq.com/s?src=11&timestamp=1611684453&ver=2852&signature=ULqQvf35tPVRg2m03zjFSspMwZAn73txF9Izl3Afhdx16j7U-WwE5VRR6m2hoqDgmCzSX2zrD*SbVyaAhRGcbsWXatJgsT-AgzqImMTF5bbuzWsHNU3BaYy1cPIKECxR&new=1

å¾ç

å¾ç

悲观锁:

å¾ç    å¾çå¾ç

乐观锁:

å¾çå¾ç

猜你喜欢

转载自blog.csdn.net/qq_24271537/article/details/113213197