悲观锁和乐观锁以及事务的隔离级别
Posted fengxiaoyuan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了悲观锁和乐观锁以及事务的隔离级别相关的知识,希望对你有一定的参考价值。
悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。
乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。
两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下,即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果经常产生冲突,上层应用会不断的进行retry,这样反倒是降低了性能,所以这种情况下用悲观锁就比较合适。
事务隔离级别共有4种:
事务隔离级别 | 脏读 | 不可重复度 | 幻读 |
1.未提交读 | 是 | 是 | 是 |
2.提交读(不可重复读) | 否 | 是 | 是 |
3.可重复读 | 否 | 否 | 是 |
4.串行化 | 否 | 否 | 否 |
mysql的默认事务隔离级别为可重复读,而Oracle、Sqlserver的默认事务隔离级别都为提交读(不可重复读)
1.InnoDB 支持表锁和行锁,使用索引作为检索条件修改数据时采用行锁,否则采用表锁。锁表时在其它的事务中执行会发生等待的现象,时间长的话会有报错提示。
2 InnoDB 自动给修改操作加锁,给查询操作不自动加锁
3.行锁相对于表锁来说,优势在于高并发场景下表现更突出,毕竟锁的粒度小。
4. 当表的大部分数据需要被修改,或者是多表复杂关联查询时,建议使用表锁优于行锁。
5.为了保证数据的一致完整性,任何一个数据库都存在锁定机制。锁定机制的优劣直接影响到一个数据库的并发处理能力和性能。
举例说明:不可重复读
1.事务隔离级别为不可重复读
2.在两个事务同时开启时
3.事务B中,在事务A操作增删改之前查询一次数据
4.事务A做了更新或删除的操作,并提交
5.事务B中,在事务A操作增删改之后查询一次数据。两次查询结果不一致,可以看见事务A中已经提交的操作
幻读:在mysql中没有实现出来,网上有好多的说法。其实过分关注概念也是没有用的,于是不在研究。
事务隔离级别为可重复读的情况下:
手动实现加锁
共享锁:select * from tableName where ... + lock in share more
排他锁:select * from tableName where ... + for update
查询事务的隔离级别:select @@tx_isolation;
设置事务的隔离级别:SET session TRANSACTION ISOLATION LEVEL Serializable;(参数可以为:Read uncommitted,Read committed,repeatable read,Serializable)
开启事务:start transaction;或者begin;
提交事务:commit;
以上是关于悲观锁和乐观锁以及事务的隔离级别的主要内容,如果未能解决你的问题,请参考以下文章
第36讲 谈谈MySQL支持的事务隔离级别,以及悲观锁和乐观锁的原理和应用场景