MySQL悲观锁和乐观锁

MySQL悲观锁和乐观锁

在数据库中,锁是用来管理并发控制的一种机制,确保数据的一致性和完整性。MySQL中的悲观锁和乐观锁是两种不同的并发控制策略,它们在处理并发事务时采用不同的方法。

悲观锁(Pessimistic Locking)

悲观锁假设会发生冲突,因此它会在事务开始时锁定数据,阻止其他事务修改这些数据,直到当前事务完成。

  • 适用场景:适用于写操作多的场景,因为写操作之间是互斥的。
  • 实现方式 :通常通过SELECT ... FOR UPDATE语句实现。
乐观锁(Optimistic Locking)

乐观锁假设冲突发生的概率较小,因此它不会在事务开始时锁定数据。相反,它会在数据提交时检查在事务执行期间数据是否被其他事务修改过。

  • 适用场景:适用于读操作多的场景,因为读操作之间不是互斥的。
  • 实现方式:通常通过版本号(version)或时间戳(timestamp)实现。

案例演示

悲观锁案例

假设我们有一个orders表,其中包含订单数据,我们希望在更新订单状态时使用悲观锁。

sql 复制代码
-- 创建表
CREATE TABLE orders (
    id INT PRIMARY KEY,
    product_name VARCHAR(100),
    order_status VARCHAR(10),
    order_amount INT
);

-- 插入测试数据
INSERT INTO orders (id, product_name, order_status, order_amount) VALUES (1, 'Laptop', 'PENDING', 1000);

使用悲观锁更新订单状态:

sql 复制代码
-- 开启事务
START TRANSACTION;

-- 锁定特定行并更新
SELECT * FROM orders WHERE id = 1 FOR UPDATE;

-- 更新订单状态
UPDATE orders SET order_status = 'SHIPPED' WHERE id = 1;

-- 提交事务
COMMIT;

在这个案例中,SELECT ... FOR UPDATE语句锁定了id = 1的行,直到事务提交,其他事务都不能修改这行数据。

乐观锁案例

假设我们有一个products表,其中包含产品信息和版本号。

sql 复制代码
-- 创建表
CREATE TABLE products (
    id INT PRIMARY KEY,
    product_name VARCHAR(100),
    version INT DEFAULT 1
);

-- 插入测试数据
INSERT INTO products (id, product_name) VALUES (1, 'Smartphone');

使用乐观锁更新产品名称:

sql 复制代码
-- 读取产品信息和版本号
SELECT id, product_name, version FROM products WHERE id = 1;

-- 假设读取到的版本号是1,现在更新产品名称和版本号
UPDATE products SET product_name = 'Updated Smartphone', version = version + 1 WHERE id = 1 AND version = 1;

-- 如果没有行被更新,说明在读取和更新之间有其他事务更新了数据

在这个案例中,我们通过版本号来实现乐观锁。当我们尝试更新产品名称时,我们会检查版本号是否与我们读取时的版本号相同。如果不同,说明在读取和更新之间有其他事务更新了数据,我们可以决定重试或者放弃更新。

总结

悲观锁和乐观锁是处理并发事务的两种策略。悲观锁适用于写操作多的场景,通过锁定数据来保证事务的一致性。乐观锁适用于读操作多的场景,通过版本控制来减少锁的开销,提高系统的并发性能。在实际应用中,选择哪种锁策略取决于具体的业务场景和性能要求。

附springboot,springcloudalibaba课程视频:

html 复制代码
<!-- springboot,springboot整合redis,整合rocketmq视频: -->
https://www.bilibili.com/video/BV1nkmRYSErk/?vd_source=14d27ec13a4737c281b7c79463687112

<!-- springcloudalibaba,openfeign,nacos,gateway,sso视频:-->
https://www.bilibili.com/video/BV1cFDEYWEkY/?vd_source=14d27ec13a4737c281b7c79463687112

<!-- vue+springboot前后端分离视频:-->
https://www.bilibili.com/video/BV1JLSEYJETc/?vd_source=14d27ec13a4737c281b7c79463687112

<!-- shiro视频:-->
https://www.bilibili.com/video/BV1YVUmYJEPi/?vd_source=14d27ec13a4737c281b7c79463687112
相关推荐
Elastic 中国社区官方博客1 小时前
使用真实 Elasticsearch 进行高级集成测试
大数据·数据库·elasticsearch·搜索引擎·全文检索·jenkins·集成测试
@_@哆啦A梦1 小时前
Redis 基础命令
java·数据库·redis
fajianchen1 小时前
MySQL 索引存储结构
数据库·mysql
想做富婆2 小时前
oracle: 多表查询之联合查询[交集intersect, 并集union,差集minus]
数据库·oracle·联合查询
xianwu5433 小时前
反向代理模块jmh
开发语言·网络·数据库·c++·mysql
Leven1995273 小时前
Flink (十三) :Table API 与 DataStream API 的转换 (一)
数据库·sql·flink
geovindu4 小时前
neo4j-community-5.26.0 create new database
数据库·mysql·neo4j
MyY_DO4 小时前
maven mysql jdk nvm node npm 环境安装
java·mysql·maven
因特麦克斯5 小时前
索引的底层数据结构、B+树的结构、为什么InnoDB使用B+树而不是B树呢
数据库
心 -5 小时前
增删改查(CRUD)操作
mysql