Select xxx for update

一. Mysql 数据库 的 RR 隔离级别下, 如果在事务中使用SELECT ... FOR UPDATE, 实现如下伪代码所描述的效果:

begin transaction
select id from t where status = false limit 1,1;
if select result is not empty;
then update status = true where id = ;
commit;

那么能实现吗? 答案是肯定的。

其实在MySQL数据库的可重复读(Repeatable Read,RR)隔离级别下,通过事务使用SELECT ... FOR UPDATE可以实现伪代码所描述的效果。以下是详细说明和实现步骤:

伪代码描述

BEGIN;
SELECT id FROM t WHERE status = false LIMIT 1 FOR UPDATE;
IF (SELECT result is not empty) THENUPDATE t SET status = true WHERE id = <the selected id>;
COMMIT;

实现步骤

在MySQL中,可重复读(RR)隔离级别可以防止幻读、脏读和不可重复读。在RR隔离级别下,使用SELECT ... FOR UPDATE可以确保选中的行在事务提交前不会被其他事务修改。

SQL 实现

  1. 开启事务

    START TRANSACTION;
    
  2. 选择并锁定符合条件的行

    SELECT id FROM t WHERE status = false LIMIT 1 FOR UPDATE;
    
  3. 检查查询结果并更新

    • 在编程语言中(如Java、Python等)处理查询结果,如果结果不为空,则进行更新操作。
    • 假设使用的是Java,示例代码如下:

Java示例

假设我们使用JDBC来实现上述逻辑,以下是一个示例代码:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class MySQLTransactionExample {public static void main(String[] args) {String url = "jdbc:mysql://localhost:3306/yourdatabase";String user = "yourusername";String password = "yourpassword";Connection conn = null;PreparedStatement selectStmt = null;PreparedStatement updateStmt = null;ResultSet rs = null;try {// 获取数据库连接conn = DriverManager.getConnection(url, user, password);conn.setAutoCommit(false); // 开启事务// 执行SELECT ... FOR UPDATEString selectSQL = "SELECT id FROM t WHERE status = false LIMIT 1 FOR UPDATE";selectStmt = conn.prepareStatement(selectSQL);rs = selectStmt.executeQuery();if (rs.next()) {int id = rs.getInt("id");// 如果查询结果不为空,执行UPDATE操作String updateSQL = "UPDATE t SET status = true WHERE id = ?";updateStmt = conn.prepareStatement(updateSQL);updateStmt.setInt(1, id);updateStmt.executeUpdate();// 提交事务conn.commit();System.out.println("Transaction committed. Row updated with id: " + id);} else {System.out.println("No rows found with status = false.");conn.rollback(); // 没有行需要更新,回滚事务}} catch (SQLException e) {e.printStackTrace();if (conn != null) {try {conn.rollback(); // 出现异常时回滚事务} catch (SQLException ex) {ex.printStackTrace();}}} finally {// 关闭资源try {if (rs != null) rs.close();if (selectStmt != null) selectStmt.close();if (updateStmt != null) updateStmt.close();if (conn != null) conn.close();} catch (SQLException ex) {ex.printStackTrace();}}}
}

关键点

  1. 事务

    • 使用 START TRANSACTION 开启事务。
    • 在更新成功后使用 COMMIT 提交事务;如果没有要更新的行或出现异常,则使用 ROLLBACK 回滚事务。
  2. 行锁

    • 使用 SELECT ... FOR UPDATE 语句锁定选中的行,防止其他事务在当前事务提交前修改这些行。
  3. 处理结果

    • 在编程逻辑中处理查询结果。如果查询返回不为空,则执行更新操作。
  4. 错误处理

    • 在出现异常时,确保回滚事务以保持数据一致性。

通过这种方式,可以确保在高并发环境下,只会有一个事务成功更新满足条件的行,从而避免竞争条件和数据不一致的问题。


二. 那么SELECT ... FOR UPDATE 语句 在MySql 中是加的读锁还是写锁呢?

在MySQL中,SELECT ... FOR UPDATE 语句会为选中的行加上写锁(也称为排他锁或X锁),而不是读锁。写锁可以防止其他事务在当前事务提交之前读取或修改这些行,从而确保数据的一致性和正确性。

写锁的作用

  • 防止并发修改:当一个事务使用SELECT ... FOR UPDATE选中行并加上写锁后,其他事务不能对这些行进行任何更新操作,直到当前事务完成(提交或回滚)。
  • 防止读取:在MySQL的默认InnoDB存储引擎下,SELECT ... FOR UPDATE选中的行也不能被其他事务读取(即使是读锁,也不能加在这些行上),确保当前事务的独占性。

示例

假设有一张名为 orders 的表,包含以下列:idstatusamount

开启事务并加锁

START TRANSACTION;SELECT id FROM orders WHERE status = 'pending' LIMIT 1 FOR UPDATE;

在上面的SQL语句中,符合条件的行会被加上写锁。其他事务在当前事务完成之前无法修改或读取这些行。

更新选中的行

UPDATE orders SET status = 'completed' WHERE id = <selected_id>;COMMIT;

举例说明并发控制

假设有两个事务T1和T2同时运行:

事务T1:

START TRANSACTION;SELECT id FROM orders WHERE status = 'pending' LIMIT 1 FOR UPDATE;  -- 假设选中了id为1的行
-- id 为 1 的行被锁定,其他事务无法读取或修改UPDATE orders SET status = 'completed' WHERE id = 1;COMMIT;

事务T2:

START TRANSACTION;SELECT id FROM orders WHERE status = 'pending' LIMIT 1 FOR UPDATE;  -- 等待T1完成,因为id为1的行被T1锁定-- 等待T1提交后,选中未被锁定的下一行UPDATE orders SET status = 'completed' WHERE id = 2;COMMIT;

在这种情况下,SELECT ... FOR UPDATE 确保了事务T1对选中行的独占访问权。只有在T1提交后,T2才能继续并对数据进行操作,从而避免了数据竞争和不一致问题。

结论

  • SELECT ... FOR UPDATE 在MySQL中为选中的行加上写锁(排他锁)。
  • 写锁确保其他事务在当前事务提交之前无法读取或修改被锁定的行。
  • 这种机制有助于在高并发环境中确保数据的一致性和正确性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/738314.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于centos8使用seafile搭建家用nas

本文详细总结了在CentOS 8下使用Seafile搭建家用NAS的全过程,涵盖了虚拟机的建立、MariaDB和Seafile的安装、防火墙端口配置、数据盘RAID1的创建、Seafile数据目录的迁移、用户管理、开机自启动设置以及静态IP地址的配置等内容,旨在为初学者提供一个完整的指南。目录 前言:1…

在Ubantu22.04中运行ORB_SLAM3并进行源码解析

在Ubantu22.04中运行ORB_SLAM3并进行源码解析 1.ORB_slam3简介 ORB-SLAM3 是一款前沿的即时定位与建图(SLAM)系统,专为大规模环境下的实时定位与三维重建设计。系统兼容多种视觉传感器配置,包括单目、立体双目以及RGB-D相机。ORB-SLAM3 采用 Oriented FAST 和 Rotated BRIE…

Joplin主题样式及markdown渲染样式更改

本文详细介绍了如何在Joplin笔记软件中更改主题样式和Markdown渲染样式,提供了具体的操作步骤和代码示例,帮助用户自定义Joplin的外观,使其更加美观和符合个人喜好。前言 Joplin是一款极佳的笔记软件,拥有开源、免费、可自定义程度高等多种优点,但其默认的软件主题和Markd…

模拟集成电路设计系列博客——9.2 电平转换器

模拟集成电路设计 9.2 电平转换器 电平转换器是集成电路设计中的一个重要部分,常用于芯片多电压域低功耗设计和I/O中。我们知道在集成电路中,I/O电压与Core电压常常处于两个不同的电压域,因此我们需要使用电平转换器(level shifter)来将I/O电压降低到Core电压,或者将Core…

泛语言计划 第二弹 函数

开始之前,我们先复习一下数学中是怎么定义函数的。 数集A和B,如果A所有数在B中都存在且只有一个数与之对应,则称B是A的函数 由此,我们可以看出一个关键词:对应。 编程中的函数也一样,只是编程中不一定是数,也可以是布尔值、字符串,甚至操作。 这个A集,我们叫他参数,B…

Kubernetes云原生存储解决方案openebs部署实践-4.0.1版本(helm部署)

Kubernetes云原生存储解决方案openebs部署实践-4.0.1版本(helm部署) 简介 OpenEBS 是一种开源云原生存储解决方案。OpenEBS 可以将 Kubernetes 工作节点可用的任何存储转化为本地或复制的 Kubernetes 持久卷。OpenEBS 帮助应用和平台团队轻松地部署需要快速、持久耐用、可靠且…

想要流程化办公,不妨了解拖拽式报表设计器!

看看拖拽式报表设计器是如何为客户降低成本、提高效率,携手进入产业分工新时代。当前,经济发展越来越快,经济水平提升的同时也给职场人提成了更高的要求。很多领域的客户都希望能实现降本、提质、增效,进入流程化办公新时代,可以先来了解低代码技术平台、拖拽式报表设计器…

代码随想录算法训练营第四十九天 | 300.最长递增子序列 674.最长连续递增序列 718.最长重复子数组

300.最长递增子序列 题目链接 文章讲解 视频讲解动规五部曲:dp[i]: 表示考虑元素i的最长子序列为dp[i] 递推公式:dp[i] = max(dp[j] + 1, dp[i]); 初始化:dp[i] = 1; 每个元素单独算一个子序列长度为1 遍历顺序:从前向后遍历 打印dp数组class Solution { public:int length…

基于LEACH路由协议的网络性能matlab仿真,包括数据量,能耗,存活节点

1.程序功能描述LEACH的原理在于它将传感器节点分为两类:簇头节点和普通节点。普通节点将数据发送给距离自己最近的簇头节点,然后簇头节点将收集到的数据融合后发送给基站。这种机制可以减少网络中节点的能耗,并且能够提高数据融合比例,减少传输数据量。本课题将分别对比lea…

高二的他已通过NOI保送北大了,让我们一起了解他的信息学奥赛学习经历吧!!!

相信关注本号的各位,对于信息学奥赛已经不陌生了,部分同学也已经开始踏入信息学的旅程,但前路茫茫,让我相信关注本号的各位,对于信息学奥赛已经不陌生了,部分同学也已经开始踏入信息学的旅程,但前路茫茫,让我们一起看看已经取得成就的同学的经历吧。今天要介绍的这位同…

VPS折腾记七搭建稍后阅读应用

1.简介 看微信公众号的时候,文章太长,可以收藏起来,但是等到晚上看的时候,发现作者已经删除了,很遗憾。wallabag能够收藏文章并且保存到服务器,让我们可以稍后阅读,而且也不怕文章丢失。 wallabag is a self hostable application for saving web pages: Save and class…

基于PSO粒子群优化的CNN-LSTM的时间序列回归预测matlab仿真

1.算法运行效果图预览 2.算法运行软件版本 matlab2022a3.部分核心程序for i=1:Iterifor j=1:Npeoprng(i+j)if func_obj(x1(j,:))<pbest1(j)p1(j,:) = x1(j,:);%变量pbest1(j) = func_obj(x1(j,:));endif pbest1(j)<gbest1g1 = p1(j,:);%变量gbest1 = pbest1(j);end…

关于领域驱动设计,大家都理解错了

翻遍整个互联网,我发现,关于领域驱动设计,大家都**理解错了**。 今天,我们尝试通过一篇文章的篇幅,给大家展示一个完全不同的视角,把“领域驱动设计”这六个字解释清楚。 ## 领域驱动设计学习资料现状领域驱动设计的概念提出已经有20年的时间了,整个互联网充斥着大量书籍…

7.4日BootlLoad总结

最近在研究单片机远程升级方法,看了网上许多资料后了解到,远程升级就是用IAP方法去烧写flash区,而IAP方法在EEPROM中有用到,也就是所说的掉电记忆,掉电不丢失的情况,而相较于51单片机,网上的资料大多是有关STM32单片机的,且使用操作系统,适合于芯片内存较大的芯片,分…

(一):小程序与服务器的链接

首原文写于18年5月,因不再想继续使用C站,现将主要文件迁移至博客园。文中涉及技术部分已相对过时,但依旧对初始web的小朋友具有一定参考价值,权且玩乐。 环境IDE:myeclipse,服务器容器Tomcat,服务端主要用servlet。创建servlet小程序与服务器链接(前端和后端的交互)的…

可视化数据看板/数字孪生大屏到底有没有实际价值?详解数据可视化的实用价值

数据驾驶舱/数据看板/可视化大屏的实际价值,取决于使用者的实际需求。华而不实?华就是实! 关于可视化大屏最广泛的争议,便是对其“华而不实”的批评,认为可视化大屏缺乏技术含量,只是一钟比较高级的“装饰品”,更是一种典型的“面子工程”。这种偏见乍一看似乎有其道理,…

osg使用整理(12):SSAO屏幕空间环境光遮蔽

一、基础概念 1、SSAO:通过将褶皱、孔洞和非常靠近墙面变暗的方法,近似模拟间接光照。SSAO称为屏幕空间环境光遮蔽 ,使用屏幕空间场景的深度而不是真实的几何体数据来确定遮蔽量,速度快效果好。2、实现原理:根据物体表面法线方向生成一个半球随机深度采样,主要看物体周围…

比赛获奖的武林秘籍:01 如何看待当代大学生竞赛中“卷”“祖传老项目”“找关系”的现象?

本文主要分析了大学生电子计算机类比赛中“卷”“祖传老项目”“找关系”的现象,结合自身实践经验,给出了相应的解决方案。比赛获奖的武林秘籍:01 如何看待当代大学生竞赛中“卷”“祖传老项目”“找关系”的现象? 正文 目前现状 对于大部分的比赛小白来说,对当前比赛的现…

2024.7.4 鲜花

今日推歌 natural Will you hold the line. 只有你还没有放弃。 When every one of them is giving up or giving in, tell me. 当其他所有人都停止了尝试,被挫折磨尽了希望。 In this house of mine,Nothing ever comes without a consequence or cost, tell me. 我所在之处,…

【python+selenium的web自动化】—— 控制浏览器

前言: 需本教程以Edge做测试,且谷歌、火狐等浏览器的逻辑都一样需要使用 selenium 模块操作 Edge 浏览器。 一、先通过pip install 模块 把selenium模块安装了,可以加一个中国源提升速度。pip install selenium -i https://pypi.tuna.tsinghua.edu.cn/simple二、需要下载Edg…