Oracle学习(十七)数据库锁在分布式系统里的应用(老板,乐观锁了解一下?~)
一、引言
随着业务量的增加,单机部署已经无法满足日常需求了,我们可能会把代码部署到多台服务器上去来进行服务的扩容,也就是负载均衡,那在这种场景下,怎么能实现锁的概念呢?
那么我们知道如果是一台主机部署的话,我们有很多方式可以实现锁的概念,比如利用synchronized关键字实现同步,或者使用reentrantLock可重入锁来在需要同步的场景,因为内存都是在一台机器上,可以很容易的实现对共享资源的锁定,但是多主机部署时,如果我们要锁定一个共享资源,显然这种方式无法满足我们的需求了,因为多主机部署时,我们每个主机要读取共享资源,可能会存在先后的顺序,那么在同时操纵一个数据时,就可能会存在一些很严重的问题了。
二、举个栗子
场景:2个用户同时对一个商品进行下单,商品库存只剩下1个,服务端会进行库存扣减。
期望结果:1个用户能下单成功,另一个用户提示库存不足
可能存在的问题:主机1和主机2同时去读取一个商品的库存,都发现是1,然后都进行了库存扣减,扣减完成后主机1进行了提交,库存被修改为0,这个时候主机2再进行提交,库存再次减1变为-1,那不就凉凉了么?
解决方案:数据库锁,分布式锁等(这篇文章只讨论数据库层面做的锁,分布式锁可以戳这里~)
三、代码实现
场景:商品库存为0 ,而此时进来了一个用户的购买线程

方式一 :update语句的原子性(行锁特性)实现乐观锁
乐观锁:乐观锁假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测
-- 3、对商品id为1的商品进行库存扣减
UPDATE T_GDS_INFO
SET GDS_STOCK = GDS_STOCK - 1
WHERE
GDS_ID = 1
AND GDS_ID IN (
-- 2、这里要再封装一个结果集给外层的update语句进行条件过滤,否则一条语句直接操作同一张表,即进行select又进行update会报错
SELECT
A.GDS_ID
FROM
(
-- 1、查询库存大于等于1的商品(带入需要扣减库存的商品id)
SELECT
GDS_ID
FROM
T_GDS_INFO
WHERE
GDS_ID = 1
AND GDS_STOCK >= 1
) A
);
上面的sql可能看着这比较绕,我们来一波简易的版本:
-- 1、当库存大于等于1时才进行库存扣减
UPDATE T_GDS_INFO
SET GDS_STOCK = GDS_STOCK - 1
WHERE
GDS_ID = 1
AND GDS_STOCK >= 1
方式二 :利用版本号实现乐观锁
思路:表里增加一个版本号的字段进行控制,每次成功更新版本号增加1,当需要进行更新操作时,先查询出版本号,然后再把查询出来的版本号作为update语句的条件带入,此时如果多个线程请求同一条数据时,查询到的版本号虽然一致,但是只有第一个提交的线程能更新成功。

-- 1、查询商品信息 得到版本号
SELECT * FROM T_GDS_INFO;
-- 2、在语句里带入查询到的版本号,每次成功更新版本号+1
UPDATE T_GDS_INFO
SET GDS_STOCK = GDS_STOCK - 1,
VERSION = VERSION + 1
WHERE
GDS_ID = 1
AND VERSION = 1
-- 3、如果同时2个订购都读取到版本号是1,然后进行库存扣减,那么第一条UPDATE语句会成功,把版本号增加变成2,而第二条UPDATE语句带入条件的版本号还是1,则会更新失败
PS:类似的还有用时间戳字段来进行版本控制的,思路类似,这里就不进行详细说明了
Oracle学习(十七)数据库锁在分布式系统里的应用(老板,乐观锁了解一下?~)的更多相关文章
- 重新学习MySQL数据库10:MySQL里的那些日志们
重新学习MySQL数据库10:MySQL里的那些日志们 同大多数关系型数据库一样,日志文件是MySQL数据库的重要组成部分.MySQL有几种不同的日志文件,通常包括错误日志文件,二进制日志,通用日志, ...
- oracle学习 十 数据库的语句优化(持续更)
平时关注Oracle数据库的网友都知道,Oracle性能优化保证了Oracle数据库的健壮性.下面就此提出需要注意的两个原则. 原则一:注意WHERE子句中的连接顺序: ORACLE采用自下而上的 ...
- oracle学习之数据库数据保存成文件
常常需要将数据库中的数据生成文档,由于比较喜欢脚本的方式,所以就需要使用spool的时候进行格式设置,以下简单整理了一下oracle中进行格式设置的一些东西,一共十八条,其实常用的也就那么几个,稍后会 ...
- Oracle学习笔记—数据库,实例,表空间,用户、表之间的关系
之前一直使用的关系型数据库是Mysql,而新公司使用Oracle,所以最近从网上搜集了一些资料,整理到这里,如果有不对的地方,欢迎大家讨论. 基本概念: 数据库:Oracle 数据库是数据的物理存储. ...
- 重新学习MySQL数据库6:浅谈MySQL的中事务与锁
『浅入深出』MySQL 中事务的实现 在关系型数据库中,事务的重要性不言而喻,只要对数据库稍有了解的人都知道事务具有 ACID 四个基本属性,而我们不知道的可能就是数据库是如何实现这四个属性的:在这篇 ...
- Oracle数据库悲观锁与乐观锁详解
数据的锁定分为两种方法,第一种叫做悲观锁,第二种叫做乐观锁.什么叫悲观锁呢,悲观锁顾名思义,就是对数据的冲突采取一种悲观的态度,也就是说假设数据肯定会冲突,所以在数据开始读取的时候就把数据锁定住.而乐 ...
- web开发中的两把锁之数据库锁:(高并发--乐观锁、悲观锁)
这篇文章讲了 1.同步异步概念(消去很多疑惑),同步就是一件事一件事的做:sychronized就是保证线程一个一个的执行. 2.我们需要明白,锁机制有两个层面,一种是代码层次上的,如Java中的同步 ...
- 数据库乐观锁和悲观锁的理解和实现(转载&总结)
数据的锁定分为两种,第一种叫作悲观锁,第二种叫作乐观锁. 1.悲观锁,就是对数据的冲突采取一种悲观的态度,也就是说假设数据肯定会冲突,所以在数据开始读取的时候就把数据锁定住.[数据锁定:数据将暂时不会 ...
- Oracle的悲观锁和乐观锁
为了得到最大的性能,一般数据库都有并发机制,不过带来的问题就是数据访问的冲突.为了解决这个问题,大多数数据库用的方法就是数据的锁定. 数据的锁定分为两种方法,第一种叫做悲观锁,第二种叫做乐观锁.什么叫 ...
随机推荐
- package controllerutil
原文链接:https://s0godoc0org.icopy.site/sigs.k8s.io/controller-runtime/pkg/controller/controllerutil imp ...
- Java 8新的时间日期库,这二十个案例看完你还学不会算我的!!!
Java对日期,日历及时间的处理一直以来都饱受诟病,尤其是它决定将java.util.Date定义为可修改的以及将SimpleDateFormat实现成非线程安全的.看来Java已经意识到需要为时间及 ...
- Shell编程—sed进阶
1多行命令 sed编辑器包含了三个可用来处理多行文本的特殊命令. N:将数据流中的下一行加进来创建一个多行组来处理. D:删除多行组中的一行. P:打印多行组中的一行. 1.1next命令 1. 单行 ...
- ZERO:从搜索用户来看SEO
http://www.wocaoseo.com/thread-63-1-1.html SEO是个奇怪的东西,一方面因为SEO流量往往占到网站流量几十个百分点,而且看上去它是免费的,因此许多人认为SEO ...
- PyQt5+Caffe+Opencv搭建人脸识别登录界面
PyQt5+Caffe+Opencv搭建人脸识别登录界面(转载) 最近开始学习Qt,结合之前学习过的caffe一起搭建了一个人脸识别登录系统的程序,新手可能有理解不到位的情况,还请大家多多指教. 我的 ...
- private protected internal public
//C#中的访问修饰符: //private,私有访问修饰符,被private访问修饰符修饰的成员只有在当前类的内部可以访问,其他地方一律不能访问[类中成员,如果不写访问修饰符则默认都是私有的] // ...
- 02.Flink的单机wordcount、集群安装
一.单机安装 1.准备安装包 将源码编译出的安装包拷贝出来(编译请参照上一篇01.Flink笔记-编译.部署)或者在Flink官网下载bin包 2.配置 前置:jdk1.8+ 修改配置文件flink- ...
- app转iap
ios打包ipa的四种实用方法(.app转.ipa) http://blog.csdn.net/oiken/article/details/49535369 手动压缩改后缀方式 这种方式与4.1的方法 ...
- openssl1.0在mac下的编译安装(踩坑精华)
之前做了一次brew版本升级,然后用pip3安装的一个python命令就无法执行了(涉及到openssl库),执行就会报一个错误. ImportError: dlopen(/usr/local/Cel ...
- Codeforces 1324E Sleeping Schedule DP
题意 给你一个长度为\(n\)的数组\(a\)和3个数字\(h,l和r\).\(t\)初始为0,每次可以使\(t=(t+a_i) \% h\)或者\(t=(t+a_i-1)\%h\),如果这时\(t\ ...