MySQL 在高并发下的 订单撮合 系统使用 共享锁 与 排他锁 保证数据一致性

栏目: 数据库 · 发布时间: 5年前

内容简介:距离上次择文发表,两月余久。2018年也即将要结束了,目前的工作依然是与这次让我有感记录这篇文章的原因是最近在使用高并发的业务常见是有很多种类的,最常见的例如

距离上次择文发表,两月余久。2018年也即将要结束了,目前的工作依然是与 区块链应用 相关的,也很荣幸在9月初受邀签约出版暂名为 《区块链以太坊DApp实战开发》 一书,预计在明年年初出版。

这次让我有感记录这篇文章的原因是最近在使用 Go 语言重写一个原来由 PHP 语言编写的 交易所订单撮合模块 的时候,发现 订单撮合 的部分 代码 在撮合的时候,为保证各表数据在并发情况下不出现读写脏乱而采用了 全局锁表 的操作。后面我采用了 共享锁 的形式进行了修改,于刚刚重写完,并进行了 并发单元测试 ,表现正常。

目录

  • 场景描述
  • 解决问题
  • 订单撮合实例
  • 共享锁 与 排他锁
    • 前置知识
    • 行锁与表锁
    • 两种行锁的特点
    • 两种行锁的加锁方式
    • 锁的释放
    • 操作例子
  • 改造代码片段

场景描述

高并发的业务常见是有很多种类的,最常见的例如 秒杀抢购 。它们都有一个共同的特点就是数据更新都比较频繁,通常涉及到多张业务表的 增改 操作,且表格越多的,要考虑的问题也越多。

订单撮合可以理解为订单买卖,拿这个为例子进行描述下在并非环境下存在哪些可能会导致数据错乱的情形。假设现在买卖手机,A用户是要买手机的,B用户是卖手机的。A的 买入单 订单1,和B的 卖出单 订单2,订单2卖出手机,一台手机卖1000元。此时A的网上的钱包余额是1001元,刚好比手机价格高,是可以成交的。

此时记录用户钱包钱数数量的是一张数据表。每次花费了钱或者增加了钱,都要更新这个表。

当这两笔订单进入到系统里面进行撮合。假设系统的订单撮合运行流程如下图所示:

MySQL 在高并发下的 订单撮合 系统使用 共享锁 与 排他锁 保证数据一致性

当判断条件进行A用户的钱包余额判断的时候,发现 1001 > 1000,结果是通过,此时准备进入“进行记录更细”步骤。但是,就在这个过程之中的时间差中,A用户使用了系统的网上提现功能,并成功转出了10元,剩余的是 1001 - 10 = 991 元。但是由于撮合系统的余额判断过程以及通过了,导致下面的交易流程依然能进行,最终A用991元买了B的1000元售价的手机。

解决问题

上述的常见问题是一个很简单的模型,现实的系统中往往是更复杂的。但是它所体现出的问题却是真实存在的,对于这类问题,有很多解决方案。其中,就可以考虑使用数据库的锁。

本文要介绍的是 MySQL数据库共享锁排他锁 ,其它的不作说明或引申。

订单撮合实例

下面的截图就是我所重写好的撮合系统原始的 PHP 代码,所使用了 表锁 的方式来解决前面的并发读写导致数据脏乱的问题。这种方式虽然是解决了问题,但是导致了 性能低下 的问题。

MySQL 在高并发下的 订单撮合 系统使用 共享锁 与 排他锁 保证数据一致性

共享锁 与 排他锁

前置知识:

  • MySQL 是数据库,不是 数据库引擎
  • MySQL有两种常用存储引擎: MyISAMInnoDB
  • MyISAM 不支持事务操作, InnoDB 支持事务操作
  • MySQL 的锁分有 行锁表锁
  • MyISAM 只有表锁
  • Innodb 行锁,表锁都有
  • 行锁中有 共享锁排他锁
  • 共享锁 简称 S锁, 排他锁 简称 X锁

行锁与表锁

简述:

  • 行锁,锁的是表中对应的行,只限制当前行的读写。

  • 表锁,锁的是整张表,限制的是整张表的数据读写。

比较:

  • 行锁,计算机资源开销大,加锁慢;会出现 死锁 ;锁定粒度最小,锁冲突的概率最低, 并发度 最高,性能高。
  • 表锁,计算机资源开销小,加锁快;不会出现 死锁 ;锁定粒度大,锁冲突的概率最高, 并发度 最低,性能低。

两种行锁的特点

共享锁

A 对数据 B 加了 共享锁,A能读取和修改数据B,C 等其它只 能读取 数据B,但是 不能修改 。直至A释放了B的锁。

排他锁

A 对数据 B 加了 排他锁,A能读取和修改数据B,C 等其它不能再对数据B加任何锁。直观体验是能修改,不能使用含有加锁动作的 select 读取。

两种行锁的加锁方式

要注意的是:

  • 行锁的实现 SQL 语句中必须要有索引的限制条件,例如含有 where id=xxx 这类语句。
  • 行锁的实现SQL语句没有索引限制条件会变成 表锁
  • InnoDB引擎 默认的 修改数据 类SQL语句, update , delete , insert 等,都会自动给涉及到的数据加上排他锁。

共享锁

  • select 的添加可以使用满足格式: select ... where 索引限制 lock in share mode 的语句。例如“select name from lgh_user where id = 1 lock in share model” 此时 id 是索引。

排他锁

  • 满足格式: select ... where 索引限制 for update 的语句

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

算法问题实战策略

算法问题实战策略

[韩] 具宗万 / 崔盛一 / 人民邮电出版社 / 2015-2 / 119.00元

第一部分 开始解决问题 第二部分 算法分析 第三部分 算法设计范式 第四部分 一些著名的算法 第五部分 基本数据结构 第六部分 树 第七部分 图一起来看看 《算法问题实战策略》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具