mysql 悲观锁使用

2024-08-25 18:28
文章标签 mysql 使用 database 悲观

本文主要是介绍mysql 悲观锁使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

悲观锁是一种数据库锁定机制,它假设每次操作都会发生并发冲突,因此在执行任何需要读取或写入数据的操作之前,先获取锁,防止其他事务对该数据进行修改。悲观锁确保了操作的独占性,以防止数据被其他事务同时修改,从而保证数据的一致性。

悲观锁分为两种:
1、共享锁(S锁):允许多个事务同时读取数据,但不能修改数据。
2、排他锁(X锁):禁止其他事务读取或修改数据,只有获取锁的事务可以操作数据。
使用场景:适用于并发度较高的场景,尤其是在可能发生数据冲突的情况下。
MySQL中,悲观锁通常是通过 SELECT ... FOR UPDATESELECT ... LOCK IN SHARE MODE 来实现的

1、 排他锁(Exclusive Lock, X锁)

场景:你想读取某条记录并在后续操作中修改它,确保在此期间没有其他事务可以读取或修改这条记录。比如:银行转账、库存管理、订单系统中的竞价 、避免重复处理的任务调度

一、银行转账

在银行系统中,确保用户账户余额的正确性至关重要。例如,进行转账时需要确保读取的余额在更新之前不会被其他事务修改。
假设我们有一个 accounts 表,存储用户的账户信息,包括 id、balance 等字段。用户从一个账户转账到另一个账户。

START TRANSACTION;-- 查询并锁定源账户的余额
SELECT balance FROM accounts WHERE id = 1 FOR UPDATE;-- 确保余额足够
-- (在应用程序中检查)
-- 假设 balance > 100-- 执行扣款操作
UPDATE accounts SET balance = balance - 100 WHERE id = 1;-- 查询并锁定目标账户的余额
SELECT balance FROM accounts WHERE id = 2 FOR UPDATE;-- 执行存款操作
UPDATE accounts SET balance = balance + 100 WHERE id = 2;COMMIT;

FOR UPDATE 确保在读取源账户的余额后,该余额不会被其他事务修改,避免了在扣款操作中可能发生的并发问题。

二、 库存管理

在库存管理系统中,确保在查询库存和更新库存数量之间没有其他事务干扰,避免超卖或库存不足的情况。

场景:
一个电子商务网站在处理用户订单时,需要确保产品库存足够并且在处理订单时不被其他订单处理影响。

START TRANSACTION;-- 查询并锁定产品库存
SELECT stock FROM products WHERE product_id = 101 FOR UPDATE;-- 确保库存足够
-- (在应用程序中检查)
-- 假设 stock >= 1-- 执行减库存操作
UPDATE products SET stock = stock - 1 WHERE product_id = 101;COMMIT;

FOR UPDATE 确保在读取产品库存后,库存数据在减库存之前不会被其他事务改变,从而避免库存数据的不一致问题。

三、订单系统中的竞价

在竞价系统中,多个用户可能会同时对同一商品进行竞价。需要确保在读取当前最高竞价后进行更新时,竞价数据不会被其他竞价操作影响。

场景:

一个在线拍卖系统允许多个用户同时对一个商品进行竞价。系统需要确保在更新最高竞价时没有其他用户同时进行操作。

START TRANSACTION;-- 查询并锁定当前最高出价
SELECT max_bid FROM bids WHERE item_id = 123 FOR UPDATE;-- 确保当前出价超过了最高出价
-- (在应用程序中检查)
-- 假设 max_bid < 500-- 更新最高出价
UPDATE bids SET max_bid = 500, bidder_id = 10 WHERE item_id = 123;COMMIT;

FOR UPDATE 确保在读取当前最高出价后,没有其他竞价操作在此时更新该数据,避免了竞价结果的不一致性。

四、 避免重复处理的任务调度

在任务调度系统中,可能需要从任务表中选择一个待处理的任务并将其标记为已处理,避免多个调度器同时处理同一个任务。
有一个 tasks 表,存储了多个待处理的任务,多个调度器(或工作线程)从中获取任务来处理。

START TRANSACTION;-- 查询并锁定一个待处理任务
SELECT id FROM tasks WHERE status = 'pending' LIMIT 1 FOR UPDATE;-- 更新任务状态为处理中
UPDATE tasks SET status = 'processing' WHERE id = 1;COMMIT;

FOR UPDATE 确保在查询到待处理任务后,没有其他调度器在此时获取同一个任务并进行处理,避免了任务重复处理的情况。

2、共享锁(Shared Lock, S锁)

一、只读操作中的一致性保障

场景:

在报表生成或分析过程中,需要从多个表中读取数据,确保在读取期间数据不会被其他事务修改,以防止数据不一致。

START TRANSACTION;-- 对数据加共享锁,确保读取期间数据不被修改
SELECT balance FROM accounts WHERE id = 1 LOCK IN SHARE MODE;-- 执行其他读取操作或分析
SELECT * FROM transactions WHERE account_id = 1 LOCK IN SHARE MODE;COMMIT;

LOCK IN SHARE MODE 会对查询的数据行加共享锁,其他事务可以继续读取这些行,但不能修改这些行(不能加排他锁)。
适用于读取操作后不需要立即修改数据的场景,例如报表生成。

二、 避免读写冲突

有一个系统需要检查用户是否有权限访问某些资源。在权限检查过程中,必须确保权限数据不会被其他事务修改。

START TRANSACTION;-- 对权限数据加共享锁,确保读取期间权限数据不被修改
SELECT permission_level FROM user_permissions WHERE user_id = 42 LOCK IN SHARE MODE;-- 根据权限数据执行相应操作
-- 在应用程序中进行进一步的权限验证COMMIT;

共享锁确保了在检查用户权限时,权限数据不会被其他事务修改,这样可以避免权限验证时的数据不一致问题。

三、 复杂查询中的数据一致性

在执行一个复杂的查询操作时,需要确保在查询的过程中,数据不会被其他事务修改。例如,统计某一段时间内的订单总数和金额。

START TRANSACTION;-- 对订单数据加共享锁,确保读取期间订单数据不被修改
SELECT COUNT(*) AS total_orders, SUM(amount) AS total_amount 
FROM orders 
WHERE order_date BETWEEN '2024-01-01' AND '2024-01-31' 
LOCK IN SHARE MODE;COMMIT;

在统计订单数据时,使用共享锁可以防止在查询过程中订单数据被其他事务修改,确保统计结果的准确性。

四、防止“脏读”的数据校验

在某些需要多次读取同一数据进行校验的场景下,可以使用共享锁来确保校验期间数据不会被其他事务修改,避免“脏读”。

START TRANSACTION;-- 第一次读取
SELECT stock FROM products WHERE product_id = 101 LOCK IN SHARE MODE;-- 假设在应用程序中有某些校验逻辑
-- 如果校验通过,再次读取SELECT stock FROM products WHERE product_id = 101 LOCK IN SHARE MODE;COMMIT;

共享锁确保在校验过程中的两次读取之间,数据不会被修改,避免了在两次读取之间发生“脏读”而导致的校验失败。

这篇关于mysql 悲观锁使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1106316

相关文章

SQL中的外键约束

外键约束用于表示两张表中的指标连接关系。外键约束的作用主要有以下三点: 1.确保子表中的某个字段(外键)只能引用父表中的有效记录2.主表中的列被删除时,子表中的关联列也会被删除3.主表中的列更新时,子表中的关联元素也会被更新 子表中的元素指向主表 以下是一个外键约束的实例展示

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

如何去写一手好SQL

MySQL性能 最大数据量 抛开数据量和并发数,谈性能都是耍流氓。MySQL没有限制单表最大记录数,它取决于操作系统对文件大小的限制。 《阿里巴巴Java开发手册》提出单表行数超过500万行或者单表容量超过2GB,才推荐分库分表。性能由综合因素决定,抛开业务复杂度,影响程度依次是硬件配置、MySQL配置、数据表设计、索引优化。500万这个值仅供参考,并非铁律。 博主曾经操作过超过4亿行数据

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间