Mysql 乐观锁 和悲观锁

Wesley13
• 阅读 769

平时看博客或技术文章的时候,经常被各种锁搞得晕晕乎乎,包括在 自旋锁、可重入锁、公平锁等等 、乐观锁、悲观锁、行锁、表锁、意向锁、排它锁等。前段时间终于把Java多线程相关的锁有机会学习了一遍。现在开始整理mysql相关的锁概念。先从乐观锁和悲观锁开始聊聊。

首先要知道,乐观锁和悲观锁不是真实存在的锁,只是两种抽象概念性的东西,就相当于Java中的接口,只是给出了一个定义,一种思想。可以根据这种思想去实现。

一、悲观锁:

1.1基本概念以及用法

     悲观锁是数据库层面实现的锁机制,他是指对于其他线程对本数据的修改是持有保守态度。在对数据操作前,首先要获取锁, 保证其他在修改期间,其他线程对数据不能进行修改。

     java 中的Synsynchronized 就是悲观锁思想的一种体现。

     mysql中,悲观锁的实现方式是:使用语句 select *  ...... forupdate  锁住当前行数据。

     如果能正确获取锁,那么其他线程要对于这条数据做修改,必须等待这个事务提交释放锁之后,才会执行。

    下面举个栗子:

     创建一张表,并开两个查询窗口。都关闭自动提交。

     建表语句:

DROP TABLE IF EXISTS `lock_demo`;
CREATE TABLE `lock_demo` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `count` int(11) DEFAULT NULL,
  `version` int(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;

INSERT INTO `lock_demo` VALUES ('1', '1', '0');

窗口1,加锁

//查询窗口1
set autocommit = 0; 

SELECT * from lock_demo where id = 1 for update;

窗口2 ,关闭自动提交,进行数据查询,可以查询出数据,表明悲观锁对于其他线程数据查询是不受影响的

set autocommit = 0; 

SELECT * from lock_demo where id = 1

当窗口 2 进行加锁或更新的时候,那么就会报错,因为一直获取不到锁,就会提示超时。

//另一个线程进行加锁SELECT * from lock_demo where id = 1 for update;
//另一个线程更新
update lock_demo set version = 2 WHERE id = 1;

错误提示信息:

[Err] 1205 - Lock wait timeout exceeded; try restarting transaction

当前线程提交事务后,其他线程才能进行更新。

1.2悲观锁的两种模式

这里引出了悲观锁涉及到的另外两个锁概念,它们就是共享锁与排它锁。

共享锁和排它锁是悲观锁的不同的实现,它俩都属于悲观锁的范畴。

  • 共享锁顾名思义,共享指的是不同事务对同一个数据可以共享一把锁,也就是说不同事务都可以读取数据。

语法: 

select * from table lock in share mode
  • 排他锁,是指对条数据加排它锁后,其他事务就不能对当前数据加锁,包括共享锁和排它锁都不可以。

语法:

select * from table for update

innodb 存储在执行修改、删除的时候,都是会默认增加排它锁。

在查询的时候,是不加任何锁的,注意不是加了共享锁,是不加任何锁的。所以才会有在第一个事务中加排它锁的时候,第二个事物依旧可以通过 select * ...... 的方式查询。

但是不能再加锁,共享锁和排它锁都不行,也就是执行    select * from table for update      select * from table lock in share mode  都不行,也就是执行update 和delete 操作都是不行的。

那么插入数据是是否受影响呢,答案是肯定不受影响。

首先,共享锁和排它锁的粒度是行,也就是针对一行数据。例如你再id = 1的数据上加了排他锁,那么id = 2的数据依旧可以更新删除,更不用说去新增一条数据了。

二. 乐观锁

  乐观锁表示对数据的更新持有乐观态度,表示不会造成冲突,所以一般是先进行业务处理,在对数据更新的时候再去判定是否有冲突。

  乐观锁是用户自己实现的,不是数据库层面的锁。

  原理就是:

    在表字段中加一个version 字段。每次更新的时候去检查当前查询的数据中的version 与数据库中的version是否相同,如果不同则不进行更新,相同则进行更新,然后将version 加1

   类似的可以使时间戳实现相同的功能。

三. 总结

3.1 实现方式

          悲观锁是数据库级别实现的,直接使用 select * .....  for update 就表示对当前数据加锁。

         乐观锁是需要自己实现,一般是通过版本控制或者加时间戳等方式实现。

3.2 适用场景

  • 乐观锁在不发生取锁失败的情况下开销比悲观锁小,但是一旦发生失败回滚开销则比较大,因此适合用在取锁失败概率比较小的场景,可以提升系统并发性能

  • 乐观锁还适用于一些比较特殊的场景,例如在业务操作过程中无法和数据库保持连接等悲观锁无法适用的地方

参考文章:https://www.cnblogs.com/cyhbyw/p/8869855.html

点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
3年前
java 里面 的锁
A、乐观锁、悲观锁B、偏向锁、轻量级锁、重量级锁C、互斥锁、自旋锁、适应性自旋D、可重入锁、读写锁E、公平锁、非公平锁F、总线锁、缓存锁(linux操作系统底层,由CPU提供的锁)G、锁优化:减少锁持有时间、减小锁粒度、锁分离、锁粗化、锁消除信号量与互斥量:信号
Wesley13 Wesley13
3年前
java中的锁
记录一下公平锁,非公平锁,可重入锁(递归锁),读写锁,自旋锁的概念,以及一些和锁有关的java类。公平锁与非公平锁:公平锁就是在多线程环境下,每个线程在获取锁时,先查看这个锁维护的队列,如果队列为空或者自身就是等待队列的第一个,就占有锁。否则就加入到等待队列中,按照FIFO的顺序依次占有锁。非公平锁会一上来就试图占
Wesley13 Wesley13
3年前
MySQL 中的共享锁和排他锁的用法
在MySQL中的行级锁、表级锁和页级锁中,咱们介绍过,行级锁是MySQL中锁定粒度最细的一种锁,行级锁能大大减少数据库操作的冲突。行级锁分为共享锁和排他锁两种,本文将详细介绍共享锁和排他锁的概念、使用方式及注意事项。共享锁(ShareLock)共享锁又称读锁,是读取操作创建的锁。其他用户可以并发读取数据,但任
Wesley13 Wesley13
3年前
MySQL 乐观锁和悲观锁
前言  1)在数据库的锁机制中介绍过,数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务同时存取数据库中同一数据时不破坏事务的隔离性和一致性以及数据库的一致性。  2)加锁是为了解决更新丢失问题更新丢失  两次更新同时进行,后一次更新覆盖了前一次更新的情况,更新丢失是数据没有保证一致性导致的。事务A查询余额,
Wesley13 Wesley13
3年前
MySQL中的共享锁与排他锁
在MySQL中的行级锁,表级锁,页级锁(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fwww.hollischuang.com%2Farchives%2F914)中介绍过,行级锁是Mysql中锁定粒度最细的一种锁,行级锁能大大减少数据库操作的冲突。行级锁分为共享锁和排他锁两种,本文将详细
Wesley13 Wesley13
3年前
Java并发编程:Java中的锁和线程同步机制
锁的基础知识锁的类型锁从宏观上分类,只分为两种:悲观锁与乐观锁。乐观锁乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,采取在写时先读出当前版本号,然后加锁操作(比较跟上一次的版本号,如果一
Wesley13 Wesley13
3年前
5分钟 BeetlSQL 快速入门
企业应用面临的问题高效编写数据库访问代码内置CRUD,不需要写SQL支持OR/Mapping悲观锁,乐观锁,逻辑删除等辅助支持等即支持简单的CRUD,也支持数十行,上百行SQL编写跨数据库平台支持,Oracle,Postgres,Mysql,以及SQLS
Wesley13 Wesley13
3年前
Java中所有锁介绍
在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类。介绍的内容如下:1.公平锁/非公平锁2.可重入锁/不可重入锁3.独享锁/共享锁4.互斥锁/读写锁5.乐观锁/悲观锁6.分段锁7.偏向锁/轻量级锁/重量级锁8.自旋锁上面是很多锁的名词,这些分类并不是全是指锁的
Stella981 Stella981
3年前
MMVC多版本并发控制&事务的特性与隔离级别
多版本并发控制(Multiversionconcurrencycontrol,MVCC)是一种思想,有很多种实现方法。乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控制主要采用的技术手段。在关系数据库管理系统里,悲观并发控制(又名“悲观锁”,PessimisticConcurrencyControl,缩写“PCC”)是一种并发控制的方法。在