【数据库】掌握MySQL事务与锁机制-数据一致性的关键

在数据库的世界里,数据就是一切。而确保数据的准确性和一致性,则是数据库系统的核心任务之一。想象一下,如果没有合适的机制,当多个用户同时试图修改同一条数据时,会发生什么? chaos(混乱)!为了避免这种情况,MySQL 使用了事务锁机制,它们就像数据库世界的交通警察,确保数据操作井然有序,避免冲突。

一、事务:要么全部成功,要么全部失败

事务,简单来说,就是把一系列数据库操作打包成一个不可分割的单元。它遵循 ACID 原则:

  • Atomicity (原子性): 事务中的所有操作要么全部成功,要么全部失败。就像银行转账,要么转出和转入都成功,要么都失败,不可能出现钱转出去了,对方却没收到的情况。
  • Consistency (一致性): 事务执行前后,数据库都必须处于一致的状态。例如,转账前后,两个账户的总金额应该保持不变。
  • Isolation (隔离性): 多个并发事务之间相互隔离,互不干扰。就像多个用户在 ATM 机上同时操作,彼此之间不会受到影响。
  • Durability (持久性): 一旦事务提交,它对数据库的修改就是永久性的,即使系统崩溃也不会丢失。

二、锁机制:控制并发访问,防止数据混乱

当多个用户同时访问数据库时,可能会出现以下问题:

  • 脏读: 一个事务读取了另一个事务未提交的数据,如果后者回滚,前者读取的数据就是无效的。
  • 不可重复读: 一个事务多次读取同一数据,但在读取过程中,另一个事务修改了该数据,导致前后读取的结果不一致。
  • 幻读: 一个事务读取了符合某些条件的记录,但在读取过程中,另一个事务插入了新的符合该条件的记录,导致前者再次读取时,发现多了一些“幻影”记录。

为了避免这些问题,MySQL 使用了锁机制,对数据进行加锁,控制并发访问。

MySQL 主要使用两种锁:

  • 共享锁 (S锁): 允许其他事务读取被锁定的数据,但不能修改。
  • 排他锁 (X锁): 禁止其他事务读取和修改被锁定的数据。

三、事务隔离级别:平衡一致性和性能

不同的应用场景对数据一致性的要求不同。为了平衡一致性和性能,MySQL 提供了四种事务隔离级别:

  • 读未提交 (Read Uncommitted): 最低的隔离级别,允许读取未提交的数据,可能会导致脏读、不可重复读和幻读。
  • 读已提交 (Read Committed): 只允许读取已提交的数据,可以避免脏读,但可能会导致不可重复读和幻读。
  • 可重复读 (Repeatable Read): 确保在同一事务中多次读取同一数据的结果是一致的,可以避免脏读和不可重复读,但可能会导致幻读。
  • 串行化 (Serializable): 最高的隔离级别,完全禁止并发访问,可以避免所有并发问题,但性能最差。

选择合适的隔离级别需要根据具体应用场景进行权衡。

四、案例分析

案例一:银行转账

  • 问题: 如何保证转账操作的原子性和一致性?
  • 解决方案: 使用事务,将扣款和加款操作放在同一个事务中。如果任何一个操作失败,则回滚整个事务,确保数据一致性。
  • 代码实现:
START TRANSACTION;UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;COMMIT;

案例二:商品库存管理

  • 问题: 如何防止超卖?
  • 解决方案: 使用排他锁,在用户下单时锁定库存记录,防止其他用户同时修改库存,确保库存数量的准确性。
  • 代码实现:
START TRANSACTION;SELECT stock FROM products WHERE id = 1 FOR UPDATE;IF stock > 0 THENUPDATE products SET stock = stock - 1 WHERE id = 1;INSERT INTO orders (product_id, quantity) VALUES (1, 1);
END IF;COMMIT;

案例三:数据统计

  • 问题: 如何保证统计结果的准确性?
  • 解决方案: 使用可重复读隔离级别,确保在统计过程中数据不会被其他事务修改,保证统计结果的一致性。
  • 代码实现:
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;START TRANSACTION;SELECT COUNT(*) FROM users;
SELECT SUM(amount) FROM orders;COMMIT;

案例四:论坛帖子点赞

  • 问题: 如何防止用户重复点赞?
  • 解决方案: 使用唯一索引和事务,确保每个用户只能对同一帖子点赞一次。
  • 代码实现:
CREATE TABLE post_likes (post_id INT NOT NULL,user_id INT NOT NULL,PRIMARY KEY (post_id, user_id)
);START TRANSACTION;INSERT INTO post_likes (post_id, user_id) VALUES (1, 1);COMMIT;

案例五:秒杀活动

  • 问题: 如何应对高并发秒杀请求,避免超卖?
  • 解决方案: 使用 Redis 缓存库存数量,并结合 MySQL 事务和锁机制,确保库存数量的准确性和一致性。
  • 代码实现:
# 伪代码
def seckill(product_id):# 从 Redis 中获取库存数量stock = redis.get(f"product:{product_id}:stock")if stock <= 0:return "秒杀结束"# 使用 Lua 脚本保证原子性lua_script = """if redis.call("get", KEYS[1]) > 0 thenredis.call("decr", KEYS[1])return 1elsereturn 0end"""result = redis.eval(lua_script, 1, f"product:{product_id}:stock")if result == 1:# 秒杀成功,创建订单create_order(product_id)return "秒杀成功"else:return "秒杀失败"

案例六:订单超时未支付自动取消

  • 问题: 如何实现订单超时未支付自动取消功能?
  • 解决方案: 使用 MySQL 事件调度器,定期扫描未支付订单,并更新订单状态为已取消。
  • 代码实现:
CREATE EVENT order_timeout
ON SCHEDULE EVERY 1 MINUTE
DO
BEGINUPDATE orders SET status = 'cancelled' WHERE status = 'unpaid' AND created_at < NOW() - INTERVAL 30 MINUTE;
END;

案例七:用户积分排行榜

  • 问题: 如何高效地查询用户积分排行榜?
  • 解决方案: 使用 Redis 的 Sorted Set 数据结构,存储用户积分信息,并定期从 MySQL 中同步数据。
  • 代码实现:
# 伪代码
def update_leaderboard():# 从 MySQL 中获取用户积分数据users = get_users_from_mysql()# 更新 Redis Sorted Setfor user in users:redis.zadd("leaderboard", {user.id: user.points})

案例八:消息队列

  • 问题: 如何实现一个简单的消息队列?
  • 解决方案: 使用 MySQL 表模拟消息队列,并结合事务和锁机制,确保消息的可靠传递。
  • 代码实现:
CREATE TABLE message_queue (id INT PRIMARY KEY AUTO_INCREMENT,message TEXT NOT NULL,status ENUM('pending', 'processed') DEFAULT 'pending'
);-- 生产者
START TRANSACTION;INSERT INTO message_queue (message) VALUES ('Hello, world!');COMMIT;-- 消费者
START TRANSACTION;SELECT * FROM message_queue WHERE status = 'pending' FOR UPDATE;-- 处理消息
UPDATE message_queue SET status = 'processed' WHERE id = 1;COMMIT;

案例九:分布式锁

  • 问题: 如何在分布式系统中实现锁机制?
  • 解决方案: 使用 MySQL 的 GET_LOCK() 和 RELEASE_LOCK() 函数,实现分布式锁。
  • 代码实现:
-- 获取锁
SELECT GET_LOCK('my_lock', 10);-- 释放锁
SELECT RELEASE_LOCK('my_lock');

案例十:数据版本控制

  • 问题: 如何实现数据版本控制,记录数据变更历史?
  • 解决方案: 使用 MySQL 触发器,在数据更新时,将旧数据插入到历史记录表中。
  • 代码实现:
CREATE TABLE products_history LIKE products;ALTER TABLE products_history ADD COLUMN version INT PRIMARY KEY AUTO_INCREMENT;CREATE TRIGGER products_update_trigger BEFORE UPDATE ON products
FOR EACH ROW
BEGININSERT INTO products_history SELECT *, NULL FROM products WHERE id = OLD.id;
END;

五、总结

事务和锁机制是 MySQL 确保数据一致性的关键机制。理解它们的原理和应用场景,对于设计和开发高并发、高可靠的数据库应用至关重要。在实际应用中,需要根据具体业务需求,选择合适的隔离级别和锁机制,在保证数据一致性的同时,最大限度地提高数据库性能。

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

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

相关文章

linux 基础网络配置文件

使用“ifconfig”命令查看网络接口地址 直接执行“iconfg”命令后可以看到ens33、10、virbr0这3个网络接口的信息&#xff0c;具体命令如下 ifconfig ##查看网络接口地址 ens33:第一块以太网卡的名称 lo:“回环”网络接口 virbr0:虚拟网桥的连接接口 查看指…

OpenCV特征提取与深度学习CNN特征提取差异

一、特征生成方式 ‌OpenCV传统方法‌ ‌手工设计特征‌&#xff1a;依赖人工设计的算法&#xff08;如SIFT、FAST、BRIEF&#xff09;提取图像中的角点、边缘等低层次特征&#xff0c;需手动调整参数以适应不同场景‌。‌数学驱动‌&#xff1a;基于梯度变化、几何变换等数学规…

五种方案实现双链路可靠数据传输

本文介绍五种双链路数据传输方案,目标是利用设备的多个传输通道,(如双有线网口,网口+wifi, 网口+5G等场景 , 网口+ 自组网, 自组网 + 5G等),将数据复制后分流、分路同时传输,以期提高数据传输可靠性,满足高可靠性传输的应用场景需求。部分方案给出了实际验证结果 。 …

【备赛】遇到的小问题-1

问题描述-1 想实现的功能是&#xff0c;通过ADC实时测量某引脚的电压及其占空比。 可以通过旋转电位器&#xff0c;更改其电压。 首先我定义了这几个变量 uint32_t adc_value;//HAL库函数里面得出的采样值(实时更新) uint32_t percentage6;//占空比&#xff0c;随着adc_val…

最大公约数

4.最大公约数 - 蓝桥云课 最大公约数 题目描述 给定两个正整数 A,B&#xff0c;求它们的最大公约数。 输入描述 第1行为一个整数 T&#xff0c;表示测试数据数量。 接下来的 T 行每行包含两个正整数 A,B。 1≤T≤105&#xff0c;1≤A,B≤109。 输出描述 输出共 T 行&…

TMHMM2.0-蛋白跨膜螺旋预测工具-centos-安装+配置+排错

参考&#xff1a; A. Krogh, B. Larsson, G. von Heijne, and E. L. L. Sonnhammer. Predicting transmembrane protein topology with a hidden Markov model: Application to complete genomes. Journal of Molecular Biology, 305(3):567-580, January 2001. centos&#x…

docker run 命令常用参数

docker run 命令 用于从镜像创建并启动一个新的容器。 基本语法&#xff1a; docker run [OPTIONS] IMAGE [COMMAND] [ARG...]常用选项分类说明 容器配置 --name 为容器指定名称&#xff08;默认随机生成&#xff09;。 示例&#xff1a; docker run --name my_container …

Zbrush插件安装

安装目录在: ...\Zbrush2022\ZStartup\ZPlugs64

pandas中excel自定义单元格颜色

writerpd.ExcelWriter(filepathf05教师固定学生占比1月{today}.xlsx,engineopenpyxl) df.to_excel(writer,sheet_name明细) piv1.to_excel(writer,sheet_name1月分布) wswriter.book.create_sheet(口径) ws.cell(1,1).value综合占比&#xff1a; ws.cell(1,2).value固定学生占比…

整体二分算法讲解及例题

算法思想 整体二分&#xff0c;带有二分二字那么就一定和二分脱不了干系。 整体二分算法常用来解决询问区间的第 k k k小值的问题&#xff0c;思路如下&#xff1a; 我们二分的对象是这道题目给定的值域&#xff0c;及最小值与最大值之间的区间&#xff0c;在题目给定的数组中…

python+flask实现360全景图和stl等多种格式模型浏览

1. 安装依赖 pip install flask 2. 创建Flask应用 创建一个基本的Flask应用&#xff0c;并设置路由来处理不同的文件类型。 from flask import Flask, render_template, send_from_directory app Flask(__name__) # 设置静态文件路径 app.static_folder static app.r…

XML转义符详解:如何在XML中正确处理特殊字符

在XML中&#xff0c;某些字符具有特殊含义&#xff0c;如果直接在文本中使用这些字符&#xff0c;可能会导致XML解析错误。为了避免这些问题&#xff0c;我们需要使用XML转义符或CDATA段来处理这些特殊字符。本文将详细介绍XML转义符的使用方法、注意事项&#xff0c;并结合实际…

IPC 进程间通信(一):管道(匿名管道进程池)

1. 初识进程间通信 1.1进程间通信的目的&#xff1a; 1、数据传输&#xff1a;一个进程需要将它的数据发送给另一个进程 2、资源共享&#xff1a;多个进程之间共享同样的资源 3、通知事件&#xff1a;一个进程需要向另一个或一组进程发送消息&#xff0c;通知它&#xff08;它…

Linux-数据结构-单链表练习-双链表

一.单链表练习和一些功能实现 【1】单链表实现字典查询 &#xff08;1&#xff09;定义存放数据的结构体&#xff0c;在每次向里面存放数据时候需要清空 &#xff08;2&#xff09;对字典进行切割 空格切割字母&#xff0c;再从剩余里切割到解释&#xff0c;这里windows的txt文…

网络爬虫相关

一、爬虫的基础内容 1、基本概念和用途 1.1、概念&#xff1a; 模拟浏览器、发送请求&#xff0c;获取响应。&#xff08;只能获取客户端所展示出来的数据&#xff09; 1.2、特点&#xff1a;知识碎片化&#xff0c;针对不同的网站对应的方法也不同。 爬虫&#xff1a;模拟…

Lora 中 怎么 实现 矩阵压缩

Lora 中 怎么 实现 矩阵压缩 1. 导入必要的库 import torch import re from datasets import Dataset from transformers import AutoTokenizer, AutoModelForCausalLM, TrainingArguments, Trainer, \get_cosine_schedule_with_warmup, EarlyStoppingCallback from peft

golang-嵌套结构体

结构体嵌套 golang中没有类&#xff0c;他通过结构体来实现其他编程语言中类的相关功能。 具名结构体 基本语法 基本语法 golang的结构体嵌套特别简单。 type 结构体类型1 struct{字段 类型1字段 类型2 }//这样就实现了结构体的嵌套 type 结构体类型2 struct{字段 类型1字…

基于Spring Boot的大学校园生活信息平台的设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

【 利用socket来实现简单远控】

利用socket来实现简单远控 &#x1f539; 免责声明⚠️ 重要提示一、什么是socket&#xff1f;二、如何使用socket来实现两台计算机之间的通信&#xff1f;服务端1、首先需要创建一个socket&#xff1b;2、绑定IP以及端口3、开启监听4、接受客户端连接5、客户端连接上之后就是命…

数据可视化在特征分布对比中的应用

数据可视化在特征分布对比中的应用 1. 引言 在机器学习系统开发和维护过程中,特征分布对比是评估数据质量和模型鲁棒性的关键环节。当训练数据与测试数据分布存在偏差,或生产环境中的数据分布随时间发生变化时,模型性能通常会显著下降。有效的数据可视化不仅能帮助检测这些…