数据库读写分离、事务的特性、事务隔离级别及默认级别、脏读不可重复读和幻读、更新丢失问题、写偏斜问题、MVCC

数据库读写分离

读写分离是将数据库的写操作和读操作分开处理,写操作全部在主库执行,读操作分布到从库中进行。

目的是提升系统并发性能(缓解了锁的争用)、降低主库负载(减少了事务分配)、提高可扩展性和可用性(增加冗余),同时利用从库实现负载均衡和高性能查询。(从服务器可以使用MyISAM)

如果从服务器采用了MyISAM:

MyISAM不支持事务和崩溃恢复,数据一致性较弱;因此,从库用MyISAM可能提高查询速度,但会导致主从数据一致性和恢复能力降低。

如果使用需要确保:

  • 主库和从库间的复制设置准确,监控同步延迟;
  • 从库仅用于只读查询,不参与写操作;
  • 明确数据一致性要求,了解潜在风险,最好保持主从使用相同引擎以保证一致性。

How:

  1. 配置主从复制,让主库将变更记录到二进制日志并同步到从库;
  2. 在应用层或通过中间件,将写请求发送到主库,读请求发送到从库;
  3. 监控同步延迟,并根据需要调整复制参数或增加从库。

事务的特性

**是什么:**事务是一组作为一个单元执行的数据库操作,满足原子性、一致性、隔离性、持久性(ACID)特性。

**为什么:**事务确保即使在错误或系统崩溃时,数据库数据仍保持一致和可靠,防止部分操作成功而部分失败带来的数据不一致问题。

怎么做:

通过使用 BEGINSTART TRANSACTION 开启事务,执行一系列操作后用 COMMIT 提交或用 ROLLBACK 撤销。

事务隔离级别及数据库默认级别

事务隔离级别定义了并发事务中,各事务之间相互"看不见"未提交数据的程度。常见的隔离级别有:

  • 读未提交(Read Uncommitted)
  • 读已提交(Read Committed)
  • 可重复读(Repeatable Read)
  • 串行化(Serializable)
    默认级别因数据库而异,例如,MySQL InnoDB默认是可重复读。

脏读不可重复读和幻读

是什么:

  • 脏读:读取到其他事务未提交的数据。
  • 不可重复读:同一事务中,多次查询同一数据返回不一致结果,因为其他事务修改了数据。
  • 幻读:同一事务中,多次执行查询出现额外的"幻影"记录,因为其他事务插入或删除了数据。

为什么:

这些现象由并发事务操作引起,隔离级别不够高时,事务之间会互相影响,导致数据不一致的问题。

怎么做:

通过设置适当的事务隔离级别来避免:

  • 脏读:可通过读已提交或更高隔离级别防止。
  • 不可重复读:可通过可重复读隔离级别防止。
  • 幻读:可通过串行化隔离级别防止或采用行级锁策略。

更新丢失问题

是什么:

数据库更新丢失问题指的是在并发更新同一数据时,由于没有正确处理更新顺序或冲突,导致部分更新被覆盖或忽略,最终数据没有反映所有预期的变更。

为什么:

  1. 并发更新时多个事务同时修改相同数据而未使用适当的锁或版本控制;
  2. 事务隔离级别设置不当导致读到脏数据或不可重复读;
  3. 应用层更新逻辑未正确考虑冲突处理,造成最后提交的事务覆盖先前的更新。

怎么做:

  1. 使用合适的事务隔离级别和锁机制(如行级锁、SELECT FOR UPDATE)确保并发更新安全;
  2. 采用乐观锁(版本号或时间戳机制)检测并解决更新冲突;
  3. 在应用层实现冲突检测和重试机制,确保所有更新都能最终正确写入。

写偏斜问题

什么是写偏斜问题:

写偏斜问题是一种并发事务问题,发生在多个事务根据条件读取数据并独立更新时,由于缺乏全局一致性检查,可能导致违反业务约束的更新。例如,两个事务在检查条件时看到的是同一状态,但在更新时导致不一致。

为什么会产生:

写偏斜的原因是事务的隔离级别不足,通常发生在 可重复读 (REPEATABLE READ) 或更低的隔离级别下。这些隔离级别保证每个事务看到的读取数据一致,但不保证全局一致性。

解决:

  • **使用更高的隔离级别 (SERIALIZABLE):**确保事务按照全局顺序串行执行,避免并发事务的检查与更新导致数据不一致。缺点:性能下降,开销增加。
  • **显式锁:**对需要检查和更新的行或表加锁,确保事务独占资源。例如:对账户表或总余额加写锁,避免并发修改。
  • **分布式事务控制:**如果是分布式场景,可以使用二阶段提交协议 (2PC) 或类似机制,确保事务的一致性。
  • **业务逻辑优化:**在应用层加约束,确保检查和更新逻辑统一,避免多个事务基于相同条件进行并发更新。

MVCC

是什么:

MVCC(多版本并发控制)是一种数据库并发控制机制,它为每个事务提供数据的快照,从而允许多个事务同时访问数据库,而不会互相阻塞。

为什么:

MVCC的目的是提高并发性能和系统吞吐量,避免因锁竞争导致的性能瓶颈,同时确保数据一致性,解决读写冲突问题。

怎么做:

数据库为每条数据维护多个版本,每个版本都有一个时间戳或事务ID。事务启动时获取一个数据快照,读操作访问快照数据,写操作则创建新版本,通过版本信息和事务状态判断数据的可见性和提交顺序。

产生背景:

  • 高并发场景的性能问题:

    在传统的锁机制中,事务为了保证一致性,会使用锁来阻止其他事务访问正在操作的数据。这种锁机制在高并发场景下容易导致大量事务等待,从而降低系统性能和吞吐量。

  • 读写冲突问题:

    事务在执行过程中,读操作和写操作之间的冲突会导致锁竞争,进一步降低并发性能。例如,一个事务正在修改某行数据,而另一个事务试图读取该数据,会造成等待或阻塞。

  • 提高一致性和隔离性:

    数据库需要满足事务的隔离级别(如可重复读),而传统锁机制容易增加复杂性和开销。MVCC 提供了一种更高效的机制,通过多版本的方式避免了锁竞争,同时满足一致性要求。

相关推荐
hao_wujing21 分钟前
攻击模型的恶意行为检测
网络·数据库·php
秃头摸鱼侠1 小时前
MySQL查询语句(续)
数据库·mysql
MuYiLuck1 小时前
【redis实战篇】第八天
数据库·redis·缓存
睡觉待开机1 小时前
6. MySQL基本查询
数据库·mysql
大熊猫侯佩2 小时前
由一个 SwiftData “诡异”运行时崩溃而引发的钩深索隐(三)
数据库·swiftui·swift
大熊猫侯佩2 小时前
由一个 SwiftData “诡异”运行时崩溃而引发的钩深索隐(二)
数据库·swiftui·swift
大熊猫侯佩2 小时前
用异步序列优雅的监听 SwiftData 2.0 中历史追踪记录(History Trace)的变化
数据库·swiftui·swift
大熊猫侯佩2 小时前
由一个 SwiftData “诡异”运行时崩溃而引发的钩深索隐(一)
数据库·swiftui·swift
Ares-Wang2 小时前
负载均衡LB》》HAproxy
运维·数据库·负载均衡
AI.NET 极客圈3 小时前
.NET 原生驾驭 AI 新基建实战系列(四):Qdrant ── 实时高效的向量搜索利器
数据库·人工智能·.net