MySQL 乐观锁 悲观锁 共享锁 排他锁

乐观锁

乐观锁是逻辑概念上的锁,不是数据库自带的,须要咱们本身去实现。乐观锁是指操做数据库时(更新操做),想法很乐观,认为此次的操做不会致使冲突,在操做数据时,并不进行任何其余的特殊处理(也就是不加锁),而在进行更新后,再去判断是否有冲突了。java

一般实现是这样的:在表中的数据进行操做时(更新),先给数据表加一个版本(version)字段,每操做一次,将那条记录的版本号加1。也就是先查询出那条记录,获取出version字段,若是要对那条记录进行操做(更新),则先判断此刻version的值是否与刚刚查询出来时的version的值相等,若是相等,则说明这段期间,没有其余程序对其进行操做,则能够执行更新,将version字段的值加1;若是更新时发现此刻的version值与刚刚获取出来的version的值不相等,则说明这段期间已经有其余程序对其进行操做了,则不进行更新操做。mysql

举例:sql

下单操做包括3步骤:数据库

1.查询出商品信息spa

select (status,version) from t_goods where id=#{id}

2.根据商品信息生成订单code

3.修改商品status为2对象

update t_goods  set status=2,version=version+1
 where id=#{id} and version=#{version};

 

悲观锁

与乐观锁相对应的就是悲观锁了。悲观锁就是在操做数据时,默认此操做会出现数据冲突,因此在进行每次操做时都要经过获取锁才能进行对相同数据的操做,这点跟java中的synchronized很类似,因此悲观锁须要耗费较多的时间。悲观锁的实现,依靠数据库提供的锁机制,使用的时候直接调用数据库的相关语句就能够了。blog

数据库上的操做能够概括为两种:读和写。多个事务同时读取一个对象的时候,是不会有冲突的。同时读和写,或者同时写才会产生冲突。事务

MyIsam引擎会为查询和更新等操做自动添加表级锁,所以它的状况比较简单。InnoDB引擎状况比较复杂,它一般会定义两种锁:共享锁和排它锁。文档

共享锁

共享锁(Shared Lock,也叫S锁)表示对数据进行读操做,加锁后其余事务能够读,但不能写。多个事务能够同时为一个对象加共享锁。

SELECT ... LOCK IN SHARE MODE走的是IS锁(意向共享锁),即在符合条件的rows上都加了共享锁,这样的话,其余人能够读取这些记录,也能够继续添加IS锁,可是没法修改这些记录直到你这个加锁的过程执行完成(完成的状况有:事务的提交,事务的回滚,不然直接锁等待超时)。

SELECT ... LOCK IN SHARE MODE的应用场景适合于两张表存在关系时的写操做,拿mysql官方文档的例子来讲,一个表是child表,一个是parent表,假设child表的某一列child_id映射到parent表的c_child_id列,那么从业务角度讲,此时我直接insert一条child_id=100记录到child表是存在风险的,由于刚insert的时候可能在parent表里删除了这条c_child_id=100的记录,那么业务数据就存在不一致的风险。正确的方法是再插入时执行select * from parent where c_child_id=100 lock in share mode,锁定了parent表的这条记录,而后执行insert into child(child_id) values (100)就不会存在这种问题了。

排它锁

排他锁(Exclusive Lock,也叫X锁)也叫写锁。加锁后,其余事务不能读取,也不能写。

若是一个事务对对象加了排他锁,其余事务就不能再给它加任何锁了。

产生排他锁的sql: SELECT ... FOR UPDATE

简单总结

共享锁适用于两张表存在业务关系时的一致性要求,排它锁适用于操做同一张表时的一致性要求。

相关文章
相关标签/搜索