美文网首页
MySQL中的乐观锁和悲观锁

MySQL中的乐观锁和悲观锁

作者: 黄二的NPE | 来源:发表于2018-04-28 15:42 被阅读13次

当我们购买一件商品时,一般会有以下几个操作:

  1. 查询商品信息
  2. 将商品信息和用户信息插入订单表
  3. 更新商品信息,比如状态更新为已被购买

当单条线程执行这些操作的时候肯定不会出现问题,但是当高并发的时候,会出现商品会重复购买的情况.这时候我们就要加锁了.
goods

CREATE TABLE `goods` (
  `id` int(11) NOT NULL COMMENT '主键id',
  `name` varchar(32) DEFAULT NULL COMMENT '商品名称',
  `status` tinyint(3) DEFAULT NULL COMMENT '商品状态 0:未被购买 1: 已被购买',
  `version` int(11) DEFAULT NULL COMMENT '版本号,每次更新版本号 + 1',
  `create_time` bigint(20) DEFAULT NULL COMMENT '创建时间(精确到毫秒)',
  `update_time` bigint(20) DEFAULT NULL COMMENT '更新时间(时间戳,精确到毫秒)',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商品表';

orders

CREATE TABLE `orders` (
  `id` int(11) NOT NULL COMMENT '注解id',
  `goods_id` int(11) DEFAULT NULL COMMENT '商品id',
  `user_id` int(11) DEFAULT NULL COMMENT '用户id',
  `status` tinyint(4) DEFAULT NULL COMMENT '订单状态 0:刚创建  1:下单完成 -1:下单失败',
  `create_time` bigint(20) DEFAULT NULL COMMENT '创建时间',
  `update_time` bigint(20) DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='订单表';


加锁可分为乐观锁和悲观锁

  • 乐观锁

乐观锁,顾名思义,它的想法比较乐观,认为每次查询都不会涉及到更新,所以只有到更新的时候再判断查询到的记录是否发生变化,如果没有发生变化就执行更新操作,如果已经发生了变化就不执行更新操作.

怎么判断数据是否发生变化

  1. 给表添加一个updateTime字段,每次更新的时候先判断updateTime是否与查询到updateTime一致,如果一致就更新数据,并且更新updateTime,否则不更新
//查询id = #id 商品 goods
SELECT id, name, status, create_time, update_time, version  FROM GOODS WHERE id = '#id';
//插入订单表
INSERT INTO ORDERS VALUES(id, goods_id, user_id,...);
//更新goods状态,这里的update_time是上面查到的goods的update_time
UPDATE GOODS SET status = 1, update_time = now()  WHERE id = '#id' AND update_time = '#update_time';
  1. 给表添加一个version字段,每次更新的时候仙判断version是否和查询到的version一致,如果一致就更新数据,并且更新version = version + 1,否则不更新(操作和update_time更新相似,只是update_time改成version)
  • 悲观锁

悲观锁,顾名思义,就是想法比较悲观,它认为每次查询都可能涉及到更新,所以在查询的时候就给记录加上锁,其它线程就不会执行更新操作了,只有等释放锁了才能执行更新操作.

怎么给记录加锁

  1. 共享锁(读锁,S锁)
SET AUTOCOMMIT = 0;
BEGIN;
SELECT id, name, status, create_time, update_time, version  FROM GOODS WHERE id = '#id' LOCK IN SHARE  MODE;
COMMIT;

在mysql事务中查询语句后面加上 lock in share mode,即可得到记录的共享锁;什么叫做共享呢?就是当共享锁还没释放的时候,其他查询用lock in share mode也可以得到记录的共享锁.那共享锁有什么用呢?共享锁被占用的记录不能被更新或者不能被select ... for update 得到排它锁,否则会被阻塞.

  1. 排它锁
SET AUTOCOMMIT = 0;
BEGIN;
SELECT id, name, status, create_time, update_time, version  FROM GOODS WHERE id = '#id' FOR UPDATE;
COMMIT;

在mysql事务中查询语句后面加上 for update 或者 更新记录的时候,即可得到记录的排它锁;什么叫做排他锁呢?排它锁被占用的记录,不允许其他线程获得他的排它锁,甚至共享锁,就是说记录不能被更新或者 其他线程的for update 到,否则会阻塞.直到排它锁释放了才能继续执行.

注意,不管是共享锁还是排它锁,当我们用不加锁的select 查询记录的时候也是可以查询到的.

相关文章

  • rails中乐观锁和悲观锁的使用

    MySQL乐观锁和悲观锁的介绍可以参考之前的一篇文章MySQL中的锁(行锁,表锁,乐观锁,悲观锁,共享锁,排他锁)...

  • 乐观锁和悲观锁

    参考来源 深入理解乐观锁与悲观锁 乐观锁的一种实现方式——CAS mysql乐观锁总结和实践 乐观锁和悲观锁 悲观...

  • 表锁和行锁

    MySQL中的锁总体可以分为悲观锁和乐观锁。悲观锁MySQL中有自带的锁。乐观锁需要自己写程序控制来实现乐观锁的功...

  • 蚂蚁面试

    1、mysql乐观锁和悲观锁的区别? 乐观锁通过MVCC,版本实现,悲观锁select... for update...

  • mysql中的乐观锁和悲观锁

    关于mysql中的乐观锁和悲观锁面试的时候被问到的概率还是比较大的。 mysql的悲观锁: 其实理解起来...

  • (4)头条mysql

    1、MySQL有哪些锁,乐观锁和悲观锁实现 如果避免、减少锁等待、团队中如何监控MySQL的锁等待的情况 锁监控:...

  • 锁的概述

    乐观锁与悲观锁 悲观锁 乐观锁和悲观锁的概念出自数据库,但在java并发包中也引入和类似的概念(乐观锁/悲观锁是一...

  • mysql的悲观和乐观锁

    谈谈mysql的悲观和乐观锁 - 周伯通的麦田 - 博客园 悲观锁 select … for update 乐观锁...

  • mysql锁

    mysql锁 性能:乐观锁,悲观锁 操作类型:读锁,写锁,都属于悲观锁 操作粒度:行锁,表锁 乐观锁:一种思想,通...

  • mysql锁记录

    mysql锁 性能:乐观锁,悲观锁 操作类型:读锁,写锁,都属于悲观锁 操作粒度:行锁,表锁 乐观锁:一种思想,通...

网友评论

      本文标题:MySQL中的乐观锁和悲观锁

      本文链接:https://www.haomeiwen.com/subject/cnzvlftx.html