基于select for update 实现数据库分布式锁
1、select for update 的基本语法
SELECT * FROM table_name WHERE condition FOR UPDATE;
2、select for update 的定义及作用
2.1 、select for update的含义是在查询数据的同时对所选的数据行进行锁定,以保证数据的一致性和并发控制。在并发环境下,多个事务可能同时对同一数据进行读取和修改。如果不加任何锁机制,就会出现脏数据的情况,即一个事务读取了另一个事务尚未提交的数据,导致数据不一致。
2.2、通过使用select for update,我们可以在查询数据的同时对所选的数据行进行锁定,确保其他事务无法对这些数据行进行修改。这种加锁机制可以有效地避免脏数据的问题,保证数据的一致性。
3、基于select for update 实现数据库分布式锁
注意事项
- select for update 必须在事务中才会生效。
- 该语法适用于mysql的innodb 数据库引擎。
java实现
package com.monika.main.system.lock.impl;import com.monika.main.system.lock.Lock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.beans.factory.InitializingBean;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;/*** @author:whh* @date: 2024-05-11 18:47* <p></p>*/@Component
public class JdbcRowLock implements Lock,InitializingBean {private static final Logger LOG = LoggerFactory.getLogger(JdbcRowLock.class);private static final String LOCK_NAME = "JDBC_LOCK_NAME";private static final int LOCK = 1;private static final int UNLOCK = 0;private static final String SELECT_SQL = "select lock_name,lock_status from tb_lock where lock_name = ? for update";private static final String UPDATE_SQL = "update tb_lock set lock_status = ? where lock_name = ?";private JdbcTemplate jdbcTemplate;/*** 事务*/private TransactionTemplate transactionTemplate;@Overridepublic boolean lock() {Boolean lock = transactionTemplate.execute(action -> {Map<String, Object> result = jdbcTemplate.queryForMap(SELECT_SQL, LOCK_NAME);int lockStatus = (int) result.get("lock_status");if (LOCK == lockStatus) {LOG.info("线程{}获取锁[{}]失败,当前锁已被占用", Thread.currentThread().getName(), LOCK_NAME);return false;}jdbcTemplate.update(UPDATE_SQL, ps -> {ps.setInt(1, LOCK);ps.setString(2, LOCK_NAME);});LOG.info("线程{}获取锁[{}]成功", Thread.currentThread().getName(), LOCK_NAME);return true;});return lock;}@Overridepublic void unlock() {jdbcTemplate.update(UPDATE_SQL, ps -> {ps.setInt(1, UNLOCK);ps.setString(2, LOCK_NAME);});LOG.info("线程{}释放锁[{}]成功", Thread.currentThread().getName(), LOCK_NAME);}@Overridepublic void interrupt() {jdbcTemplate.update(UPDATE_SQL, ps -> {ps.setInt(1, UNLOCK);ps.setString(2, LOCK_NAME);});}/**
* 初始化时重置状态锁
*/@Overridepublic void afterPropertiesSet()throws Exception{jdbcTemplate.update(UPDATE_SQL, ps -> {ps.setInt(1, UNLOCK);ps.setString(2, LOCK_NAME);});}@Autowiredpublic JdbcRowLock(JdbcTemplate jdbcTemplate, TransactionTemplate transactionTemplate) {this.jdbcTemplate = jdbcTemplate;this.transactionTemplate = transactionTemplate;}
}相关文章:
基于select for update 实现数据库分布式锁
1、select for update 的基本语法 SELECT * FROM table_name WHERE condition FOR UPDATE;2、select for update 的定义及作用 2.1 、select for update的含义是在查询数据的同时对所选的数据行进行锁定,以保证数据的一致性和并发控制。在并发环境下,多…...
Java后端实现对象与文件接收数据(minio测试)
实现思路: 1. 两个接口实现,一个接对象数据(file),一个接文件数据(json)。 2. json对象(base64String) 实体类信息 ,请求体统一接收 3. file, String name ,String password ,String name , Controller层接收 统一…...
考研踩坑经验分享
文章目录 写在前面自身情况简介自身学习路线优点坑点 学习路线建议1、2和3月份3、4和5月份6、7和8月份9、10月份11、12月份 一些私货建议结尾 写在前面 考研是一件非常有盼头的事,但绝对不是一件容易的事。 如果你不能做好来年三月份出成绩时,坦然接受…...
Android Compose 一:基础控件
Flutter 与 Compose 组件辣么像,难道是同一个google团队整的;也未深究,只是猜测。 创建项目 需要使用新版本Android studio,忽略步骤… 项目目录 MainActivity说明 1 系统默认页面 Preview 修饰的方法,只用来供开发…...
python3.12.0 在Linux 制作镜像包 部署到docker 全过程
项目结构: 比如,在pycharm里需要运行 themain.py 1、上传Linux的目录结构: Dockerfile 文件需要制作: 这里是关键: #基于的基础镜像 FROM python:3.12.0 #代码添加到code文件夹 ADD ./EF_NFCS /code #设置code文…...
STM32理论 —— μCOS-Ⅲ(新)
文章目录 1. 任务调度器1.1 抢占式调度 μCos-Ⅲ全称是Micro C OS Ⅲ,由Micriμm 公司发布的一个基于C 语言编写的第三代小型实时操作系统(RTOS); RTOS 与裸机相比最大的优势在于多任务管理与实时性,它提供了多任务管理和任务间通信的功能&a…...
衢州知识付费系统报价,教师如何做精品课程?怎么创造精品课程?
精品课程对于学生的意义来说是不同的,越是精品让学习的人就越觉得值得,所以,做为教师来说,做出精品课程不仅仅是对学生负责,也是对自己负责,那如何做精品课程?相信很多教师们也想知道。 如何创造精品课程?…...
在Vue中,可以通过使用<slot>元素和name属性来创建具名插槽。这样您就可以为一个组件的不同部分定义不同的内容。 以下是一个简单的示例:
在Vue中,可以通过使用元素和name属性来创建具名插槽。这样您就可以为一个组件的不同部分定义不同的内容。 以下是一个简单的示例: <template><div><header><slot name"header"></slot></header><mai…...
C++笔试强训day19
目录 1.小易的升级之路 2.礼物的最大价值 3.对称之美 1.小易的升级之路 链接 模拟就行,唯一可能是难点得就是gcd(最大公约数) #include <iostream> using namespace std; #define int long long const int N 1e5 10; int arr[N];…...
MySQL软件安装基于压缩包
打开mysql官网网址 MySQL :: Download MySQL Community Server 本次针对版本8的安装包方式进行安装,下载成功后接下来对MySQL进行安装 下载后有一个以zip后缀结尾的压缩包文件 对于安装包方式安装,比起可视化安装省去了许多安装步骤,这里直接…...
04 贝尔曼最优公式
贝尔曼最优公式 前言1、Motivating examples2、Definition of optimal policy3、Bellman optimality equation(BOE):Introduction4、 BOE:Maximization on the right-hand side5、BOE:Rewrite as v f(v)6、Contraction mapping theorem7、BO…...
印象笔记使用技巧
印象笔记(Evernote)是一款广泛使用的笔记应用,它帮助用户整理个人信息、文件和备忘录。以下是一些提高在印象笔记中效率的使用技巧: ### 1. 使用标签和笔记本组织笔记 - **建立笔记本**:为不同的项目或类别创建笔记本…...
产品设计中的“注册”说明
在使用网站或应用的时候必不可少的就是账号系统,账号系统有些人可能觉得简单,无非就是账号密码。真的是这样吗? 一个完整的账号系统通常大家会分成四部分: 1.注册(手机号、邮箱、用户名/密码限制/验证码)…...
【linux学习】多线程(1)
文章目录 线程的概念线程与进程 线程的用法线程的创建多线程 线程的等待线程锁死锁 线程的概念 在Linux中,线程(Thread)是程序执行流的最小单位,是进程中的一个实体,负责在程序中执行代码。线程本身不拥有系统资源&…...
Leetcode 3149. Find the Minimum Cost Array Permutation
Leetcode 3149. Find the Minimum Cost Array Permutation 1. 解题思路2. 代码实现 题目链接:3149. Find the Minimum Cost Array Permutation 1. 解题思路 这一题的话就是一个动态规划的问题,不过他这个错位着实是把题目变得复杂了不少,唉…...
Python | 为列表中的元素分配唯一值
我们可以给列表中的所有数字分配一个唯一的值,重复时它会保留给它的值。这是一个非常常见的问题,在Web开发中,处理物品id时会遇到。让我们讨论一下解决这个问题的一些方法。 1. 使用enumerate() 列表解析 # initializing list test_list …...
HTML炫酷的相册
目录 写在前面 HTML简介 完整代码 代码分析 系列推荐 写在最后 写在前面 本期小编给大家带来一个炫酷的旋转相册,快来解锁属于你的独家记忆吧! HTML简介 HTML(全称为超文本标记语言)是一种用于创建网页结构和内容的标记语…...
C++笔试强训day20
目录 1.经此一役小红所向无敌 2.连续子数组最大和 3.非对称之美 1.经此一役小红所向无敌 链接 简单模拟即可。 需要注意的是: 除完之后有无余数,若有,则还可以再挨一次打。 #include <iostream> using namespace std; #define in…...
【PHP【实战项目】系统性教学】——使用最精简的代码完成用户的登录与退出
👨💻个人主页:开发者-曼亿点 👨💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨💻 本文由 曼亿点 原创 👨💻 收录于专栏:…...
Linux下的常用基本指令
基本指令 前言一、ls 指令语法功能常用选项举例注意要点关于拼接关于 -a关于文件ls与/的联用ls与根目录ls与任意文件夹ls与常用选项与路径 ls -d与ls -ldls与ll 二、pwd命令语法功能常用选项注意要点window与Linux文件路径的区别家目录 三、cd 指令语法功能举例注意要点cd路径.…...
wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分: 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...
