当前位置: 首页 > news >正文

【并发编程】MySQL锁及单机锁实现

目录

一、MySQL锁机制

1.1 按锁粒度划分

1.2 按锁功能划分

1.3 InnoDB锁实现机制

(1)记录锁(Record Lock)

(2) 间隙锁(Gap Lock)

(3) 临键锁(Next-Key Lock)

(4) 插入意向锁(Insert Intention Lock)

二、基于 JVM 本地锁实现,保证线程安全

2.1 线程不安全的分析

2.1.1 多线程并发访问(未加锁)

2.2 基于 synchronized 加锁访问

2.3 基于 synchronized 加锁访问

2.4 JVM 本地锁的缺陷

三、基于 MySQL 锁实现,保证线程安全问题

3.1 基于原子 SQL 实现

3.2 基于悲观锁实现(灵活多 SQL )

3.2.1 原生 SQL 实现

3.2.2 Java 代码实现

3.2.3 悲观锁优缺点

3.2.4 死锁演示

3.3 基于乐观锁实现(CAS)

3.3.1 原生SQL实现

3.3.2 Java 代码实现

3.3.3 乐观锁存在的问题

四、本地不同类型锁的总结


一、MySQL锁机制

1.1 按锁粒度划分

  • 表级锁​:锁定整张表

    • 优点:开销小,加锁快
    • 缺点:并发度低
    • 实现:LOCK TABLES语句或存储引擎自动加锁
  • 行级锁​:锁定单行记录

    • 优点:并发度高
    • 缺点:开销大,加锁慢
    • 实现:InnoDB通过索引实现
  • 页级锁​:锁定一页(16KB)

    • 折中方案,BDB引擎使用

1.2 按锁功能划分

  • 共享锁(S锁)​​:

    • 语法:SELECT ... LOCK IN SHARE MODE
    • 特性:多个事务可同时获取,但不能与排他锁共存
  • 排他锁(X锁)​​:

    • 语法:SELECT ... FOR UPDATE
    • 特性:独占锁,其他事务不能获取任何锁
  • 意向锁(Intention Lock)​​:

    • 表级锁,表示事务将要获取行锁
    • IS锁(意向共享锁):事务准备给行加S锁
    • IX锁(意向排他锁):事务准备给行加X锁

1.3 InnoDB锁实现机制

(1)记录锁(Record Lock)
  • 锁定索引中的单条记录
  • 实现方式:通过索引项加锁
(2) 间隙锁(Gap Lock)
  • 锁定索引记录间的间隙
  • 防止幻读问题
  • 示例:SELECT * FROM t WHERE id > 10 AND id < 20 FOR UPDATE
(3) 临键锁(Next-Key Lock)
  • 记录锁+间隙锁的组合
  • 锁定记录及记录前的间隙
  • InnoDB默认行锁算法
(4) 插入意向锁(Insert Intention Lock)
  • 特殊的间隙锁
  • 多个事务在相同间隙插入不同记录时不冲突

二、基于 JVM 本地锁实现,保证线程安全

2.1 线程不安全的分析

多线程环境下多个线程(并发用户访问)访问同一个共享资源,并对资源进行修改(触发了线程安全问题)。

接下来只关注 Service 层的逻辑实现

2.1.1 多线程并发访问(未加锁)

1. 创建多线程环境下生产级减库存案例

@Service
public class StockService {private Stock stock = new Stock();public void deduct(){stock.setStock(stock.getStock()-1);System.out.println("扣减成功,剩余库存:"+stock.getStock());}
}

2. 运行项目,通过 JMeter 进行并发测试

查看聚合报告,样本数量为 5000 次,吞吐量为 1900个事务/秒 左右。

3. 查看项目日志:发生超卖现象。

此时查看 MySQL 表中的 1001 商品编号的第一条记录,校验库存数量是否为0:

2.2 基于 synchronized 加锁访问

1. 修改减库存的方法,进行加锁操作:synchronized 直接修改方法(底层是基于 Monitor 实现)

http://www.dtcms.com/a/178973.html

相关文章:

  • [数据库之十四] 数据库索引之位图索引
  • Mac 平台获取地区标识符号
  • 2025最新免费视频号下载工具!支持Win/Mac,一键解析原画质+封面
  • 【NextPilot日志移植】整体功能概要
  • SpringBoot3 + Druid + DynamicDataSource + PgSQL 连接池优化方案
  • spring中RequestContextHolder
  • 【WEB3】区块链、隐私计算、AI和Web3.0——隐私计算(2)
  • AI赋能高频PCB信号完整性优化
  • Ubuntu上安装MySQL 8并配置Navicat远程连接
  • Redis如何实现分布式锁
  • CFCA受邀参加盛京银行手机银行7.0发布会
  • crontab
  • 5月8日星期四今日早报简报微语报早读
  • 红外遥控与NEC编码协议详解
  • C#学习7_面向对象:类、方法、修饰符
  • 【AI】DeepWiki 页面转换成 Markdown 保存 - Chrome 扩展
  • 【速通RAG实战:索引】5.RAG分块策略与Embedding技术
  • React -> AI组件 -> 调用Ollama模型, qwen3:1.7B非常聪明
  • 基础算法系列——树的入门
  • Linux_进程退出与进程等待
  • (14)Element Plus项目综合案例
  • 在Hugging Face网站像Github一样克隆repository到本地的具体步骤
  • bootstrap入门
  • 从代码学习深度学习 - 单发多框检测(SSD)PyTorch版
  • nputop:交互式 Ascend NPU 进程查看器(nvitop昇腾版)
  • 谷云科技iPaaS技术实践:集成平台如何解决库存不准等问题
  • Pycharm安装后打开提示:此应用无法在你的电脑上运行,若要找到合适于你的电脑的版本,请咨询发布者
  • Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0.
  • Docker 核心目录结构
  • Python从入门到高手8.3节-元组的常用操作方法