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
相关推荐
要努力啊啊啊2 分钟前
使用 Python + SQLAlchemy 创建知识库数据库(SQLite)—— 构建本地知识库系统的基础《一》
数据库·人工智能·python·深度学习·自然语言处理·sqlite
KENYCHEN奉孝3 分钟前
Django CMS 的 Demo
数据库·sqlite
为中华崛起而奋斗26 分钟前
Oracle 19c RAC集群ADG搭建
数据库·oracle
betazhou2 小时前
mariadb5.5.56在centos7.6环境安装
android·数据库·adb·mariadb·msyql
开挖掘机上班2 小时前
mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
数据库·mysql
花月C2 小时前
Mysql-定时删除数据库中的验证码
数据库·后端·mysql·spring
success_a4 小时前
大故障:阿里云核心域名爆炸了
数据库·阿里云·云计算
@小红花6 小时前
MySQL数据库从0到1
数据库·mysql·oracle
[听得时光枕水眠]7 小时前
MySQL基础(三)DQL(Data Query Language,数据查询语言)
数据库·mysql·oracle