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

java基础(十)sql的mvcc

一、事务特性与实现原理

1. ACID特性详解

特性说明实现机制生活案例
原子性事务操作要么全部成功,要么全部回滚Undo Log网购:支付成功则商品发货,支付失败则资金退回
一致性事务前后数据库保持完整性约束ACID共同保证转账:A账户-200、B账户+200后,总额保持不变
隔离性并发事务相互隔离,互不干扰MVCC/锁机制电影院售票:多个售票窗口同时卖票不会出售同一座位
持久性事务提交后数据永久存储,故障不丢失Redo Log银行存钱:柜台确认存款后,即使断电记录也不会丢失

2. 事务实现机制


  • Undo Log:记录数据修改前的状态,用于事务回滚

    -- 更新前记录旧值到Undo Log
    UPDATE users SET balance=800 WHERE id=1; 
    -- Undo Log: {id:1, balance:1000}

  • Redo Log:记录物理修改,确保故障恢复

    /* 修改流程:
    1. 内存更新Buffer Pool 
    2. 写Redo Log: "pageX offsetY更新为800"
    3. 后台刷脏页到磁盘 */

二、并发问题与解决方案

1. 三大并发问题

问题类型现象描述案例场景
脏读读取到未提交的临时数据财务系统看到未提交的工资调整,导致报表错误
不可重复读同事务内两次读取结果不一致机票查询:第一次看到余票3张,付款时提示余票0
幻读同条件查询返回的记录数不同统计在线用户:第一次10人,刷新后变成12人

2. 隔离级别对比

隔离级别脏读不可重复读幻读实现方式
读未提交(Read Uncommitted)直接读最新数据
读已提交(Read Committed)每次SELECT前生成Read View
可重复读(Repeatable Read)事务开始生成Read View
串行化(Serializable)读写锁阻塞访问

:MySQL默认隔离级别为可重复读,能解决幻读大部分场景

3. 幻读特殊场景示例

-- 事务A(YA33操作)
BEGIN;
SELECT * FROM orders WHERE amount>1000; -- 返回0条
​
-- 事务B插入并提交
INSERT INTO orders VALUES(5,2000,'B');
​
-- 事务A尝试更新"不存在"的数据
UPDATE orders SET user='YA33' WHERE amount>1000; -- 影响1行
SELECT * FROM orders WHERE amount>1000; -- 出现幻读!

解决方案:对关键操作使用锁定读

SELECT * FROM orders WHERE amount>1000 FOR UPDATE; -- 加Next-Key Lock

三、MVCC多版本并发控制

1. 核心组件

组件作用
Read View事务的数据快照
trx_id记录最后修改事务ID的隐藏列(当前的事务被那个id维护)
roll_pointer指向Undo Log旧版本链的指针(指向你的老数据)

2. Read View工作流程

首先read view 维护了四个关键的数据

  • 当前事务的id

  • 未提交事务id(维护很多已经开始未提交,安升序排序)

  • 未开始事务id

========================================================================

  • 当一个读取事务进来,与最小的活跃事务id进行比较,小就读,不小就继续

  • 然后与最大的事务id进行比较,大就不读,小就继续

  • 判断是否与本身的事务id相等,相等就读,不相等就继续

  • 判断是否在活跃事务列表里面,在就不读,不在就读

3. 不同隔离级别的Read View

  • 读已提交:每次SELECT生成新Read View

  • 可重复读:首次SELECT生成Read View,整个事务复用

四、锁机制深度剖析

1. 锁类型全景


2. 行锁冲突矩阵

X(排他锁)S(共享锁)
X锁冲突冲突
S锁冲突兼容

3. 锁优化实践

场景1:范围更新不阻塞

-- 事务A(YA33操作)
UPDATE users SET score=score+1 WHERE id<10; -- 锁(-∞,10)
​
-- 事务B
UPDATE users SET vip=1 WHERE id>15;        -- 锁(15,+∞) 不冲突

场景2:无索引全表锁

-- 无索引字段更新导致全表锁
UPDATE products SET status=0 WHERE name LIKE '%清仓%'; -- 慎用!

五、日志系统工作原理

1. 日志类型对比

日志类型层级作用关键特性
Redo Log存储引擎层故障恢复物理日志,顺序写
Undo Log存储引擎层事务回滚/MVCC逻辑日志,链式存储
BinlogServer层主从复制/数据恢复逻辑日志,三种格式
Relay LogServer层从库中转主库Binlog临时中转日志

2. Binlog三种格式

格式优点缺点适用场景
STATEMENT日志量小函数结果可能不一致简单SQL
ROW数据绝对一致日志量大数据安全要求高
MIXED自动选择最优模式切换策略复杂通用场景

3. 两阶段提交流程

崩溃恢复规则

  • 发现Prepare的Redo Log:检查Binlog

    • Binlog存在 → 提交事务

    • Binlog不存在 → 回滚事务

六、性能调优实战

1. EXPLAIN关键字段解读

EXPLAIN SELECT * FROM users WHERE name='YA33';
字段优化建议
typeref理想范围:const/ref/range
keyidx_name实际使用索引名
rows1扫描行数越少越好
ExtraUsing index出现Using filesort需优化

2. 常见优化方案

场景1:深分页优化

-- 低效写法
SELECT * FROM logs ORDER BY id LIMIT 1000000,10;
​
-- 高效写法(YA33操作)
SELECT * FROM logs WHERE id>1000000 ORDER BY id LIMIT 10;

场景2:索引失效避免

- SELECT * FROM users WHERE YEAR(create_time)=2023; -- 索引失效
+ SELECT * FROM users WHERE create_time BETWEEN '2023-01-01' AND '2023-12-31';

3. 强制索引使用

-- 优化器选错索引时干预
SELECT /*+ INDEX(products idx_price) */ * 
FROM products FORCE INDEX(idx_price)
WHERE price BETWEEN 100 AND 500;

七、高可用架构

1. 主从复制流程

2. 分库分表策略

拆分方式特点适用场景
垂直分库按业务拆分(订单/用户)业务耦合度低
水平分库数据分片到不同服务器单库性能瓶颈
垂直分表大表拆小表(商品+商品详情)字段访问频率差异大
水平分表单表数据拆分(按用户ID取模)单表数据量超大

示例:订单表分片

-- 原始表
CREATE TABLE orders (id BIGINT, user_id INT, amount DECIMAL);
​
-- 分片后(YA33的user_id=12345)
INSERT INTO orders_5 (user_id,amount) VALUES (12345,99.9); 
-- 分片规则: user_id % 10 = 5 → orders_5

通过全面理解MySQL的事务机制、锁策略、日志系统及优化技巧,可构建高性能高可用的数据库架构。在实际应用中,需根据业务场景灵活选择隔离级别、锁机制和分片策略,如YA33在处理金融交易时应采用串行化隔离级别,而在用户日志分析场景可使用读已提交级别提升并发性能。

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

相关文章:

  • WebSocket--精准推送方案(二):实时消息推送-若依项目示例
  • 本地处理不上传!隐私安全的PDF转换解决方案
  • java_spring boot 中使用 log4j2 及 自定义layout设置示例
  • Ansible 管理变量和事实
  • 计算机毕设选题推荐-基于大数据的全面皮肤病症状数据可视化分析系统【Hadoop、spark、python】
  • 麒麟V10静默安装Oracle11g:lsnrctl、tnsping等文件大小为0的解决方案
  • Android 对话框 - 基础对话框补充(不同的上下文创建 AlertDialog、AlertDialog 的三个按钮)
  • Pandas数据结构详解Series与DataFrame
  • 智能汽车领域研发,复用云原始开发范式?
  • 笔记本电脑wifi小图标不见了 或者 蓝牙功能消失、电脑开不开机解决方法
  • 深入理解C#特性:从应用到自定义
  • CentOS启动两个MySQL实例
  • C#对象的本地保存与序列化详解笔记
  • [每周一更]-(第155期):Go 1.25 发布:新特性、技术思考与 Go vs Rust 竞争格局分析
  • 【前端面试题】前端面试知识点(第三十一题到第六十一题)
  • 项目发布上线清单
  • neo4j导入导出方法
  • 《设计模式》抽象工厂模式
  • 链表OJ题讲解---试金石含金量
  • RabbitMQ入门:生产者和消费者示例
  • Java注解学习记录
  • 什么是EDA(Exploratory Data Analysis,探索性数据分析)
  • AI出题人给出的Java后端面经(十七)(日更)
  • 第 463 场周赛(GPT-3,Me-1)
  • Foreign-Memory Access API外部内存API
  • 混沌工程(Chaos engineering):系统韧性保障之道
  • 计算机网络 HTTPS 全流程
  • p5.js 3D 形状 “预制工厂“——buildGeometry ()
  • 【位运算】查询子数组最大异或值|2693
  • 图灵完备(Turing Complete)免安装中文版