MySQL MVCC

MySQL MVCC

MySQL MVCC 内容

MVCC(Multi-Version Concurrency Control),即多版本并发控制,是MySQL中InnoDB存储引擎实现的一种并发控制机制。它通过为每个事务维护一个数据快照(ReadView)来实现,允许读写操作并发执行,同时保持数据的一致性和隔离性。MVCC主要依赖于隐藏字段、Undo日志和ReadView来实现。

隐藏字段

在InnoDB中,每条记录除了我们看到的业务字段外,还包含了一些隐藏字段,如:

  • DB_TRX_ID:6字节的事务ID,表示最后修改这条记录的事务ID。
  • DB_ROLL_PTR:7字节的回滚指针,指向这条记录的上一个版本,保存在Undo日志中。
  • DB_ROW_ID(如果表没有主键):6字节的隐藏主键,用于唯一标识记录。

Undo日志

Undo日志是InnoDB中用于实现MVCC的重要组件之一。它记录了数据被修改前的版本,以便在需要时能够回滚到某个特定的历史版本。Undo日志分为两种:

  • Insert Undo日志:在插入操作中生成,由于插入的记录对其他事务不可见,故在事务提交后可直接删除。
  • Update/Delete Undo日志:在更新或删除操作中生成,用于支持MVCC和事务回滚,不会在事务提交时立即删除,而是由专门的purge线程处理。

ReadView

ReadView是事务进行快照读时生成的数据读视图,它记录了事务开始时系统中活跃的事务ID列表、最小事务ID、最大事务ID等信息。ReadView用于判断数据版本的可见性。

MVCC 如何解决脏读、幻读、不可重复读问题

脏读(Dirty Read)

脏读是指一个事务读取到了另一个事务未提交的数据。在MVCC中,由于每次查询都是基于事务开始时创建的快照(ReadView),因此无法读取到其他事务未提交的数据,从而避免了脏读。

不可重复读(Nonrepeatable Read)

不可重复读是指在同一事务内,多次读取同一数据集合时,由于其他事务的更新操作,导致读取的数据不一致。MVCC通过为每个事务提供独立的数据快照(ReadView),使得事务内多次查询的结果保持一致,从而避免了不可重复读。

幻读(Phantom Read)

幻读特指在同一事务内,后面的查询比前面的查询多看到了记录,就像产生了幻觉一样。在MySQL的InnoDB存储引擎中,虽然可重复读(Repeatable Read)隔离级别解决了大部分幻读问题(对于快照读),但它仍然不能完全避免幻读,特别是在当前读(如使用SELECT ... FOR UPDATE)的情况下。

然而,通过结合InnoDB的间隙锁(Gap Lock)和Next-Key Lock(一种间隙锁和记录锁的组合),MySQL可以在更高层次上解决幻读问题。间隙锁能够锁定一个范围,防止其他事务在这个范围内插入新记录,从而避免了幻读。

总结

MVCC是MySQL中InnoDB存储引擎实现并发控制的核心机制,它通过维护数据的多个版本来实现读写操作的并发执行,同时保持数据的一致性和隔离性。MVCC通过隐藏字段、Undo日志和ReadView等组件,有效地解决了脏读、不可重复读和幻读等问题,提高了数据库的并发性能和数据的一致性。

在使用MVCC时,建议结合InnoDB存储引擎、适当的事务隔离级别以及合理的事务控制机制,以确保数据的一致性和并发性。

Read more

RocketMQ消息的文件组织形式

RocketMQ消息的文件组织形式

RocketMQ文件的组织形式主要围绕消息的高效存储与检索设计,主要包括CommitLog、ConsumeQueue和IndexFile三类文件。以下是对这三类文件组织形式的详细阐述: 1. CommitLog文件 * 作用:CommitLog是消息存储的主体文件,用于存储Producer端写入的消息主体内容。 * 组织形式: * 所有topic的消息都存储在同一个CommitLog文件中,确保消息发送时按顺序写文件,以追求极致的消息存储性能和高吞吐量。 * 单个文件大小默认1G,文件名长度为20位,左边补零,剩余为起始偏移量。例如,第一个文件名为00000000000000000000,代表起始偏移量为0,文件大小为1G。当第一个文件写满后,第二个文件名为00000000001073741824,以此类推。 * 存储内容:消息内容不是定长的,每条消息在CommitLog中的存储结构包括消息长度、消息体、消息属性等。 2. ConsumeQueue文件 * 作用:ConsumeQueue是消息消费队列文件,主要用于提高消息消费的性

By Zhewen Cao
记一次消息推送业务的探索

记一次消息推送业务的探索

什么是服务端消息推送 服务端消息推送(Push Notification)是一种技术概念,指的是从服务端实时发送信息到客户端的过程。在移动互联网和Web应用中,服务端消息推送被广泛用于提升用户体验、增加用户粘性和活跃度。以下是服务端消息推送的详细解释: 定义 服务端消息推送,简称推送(Push),是指服务器主动向客户端发送信息,而无需客户端显式请求。这种方式使得信息能够实时地到达用户,无需用户手动刷新页面或应用。 实现方式 服务端消息推送的实现方式多种多样,主要包括以下几种: 1. 短轮询(Short Polling): * 客户端定时向服务器发送请求,询问是否有新消息。 * 优点:实现简单。 * 缺点:实时性差,服务器资源消耗大。 2. 长轮询(Long Polling): * 客户端向服务器发送请求后,服务器会保持连接,直到有新消息才返回响应并关闭连接。 * 优点:相比短轮询,实时性更好,资源消耗更少。

By Zhewen Cao
Redis Stream:构建高效、可靠的消息队列新选择

Redis Stream:构建高效、可靠的消息队列新选择

引言 随着分布式系统的日益复杂,消息队列作为一种重要的中间件,在解决系统间异步通信、负载均衡、数据缓冲等方面发挥着不可替代的作用。Redis,作为一个高性能的键值存储系统,在5.0版本中引入了Stream这一新的数据结构,为构建高效、可靠的消息队列提供了新的选择。本文将深入探讨Redis Stream的架构、特性及其在消息队列中的应用。 Redis Stream概述 Redis Stream是Redis 5.0版本引入的一种新的数据结构,它提供了一种持久化的、可查询的、可扩展的消息队列服务。Stream类型的数据结构类似于一个日志系统,数据被添加到Stream的末尾,并且每个数据都会被分配一个唯一的序列号(Entry ID),这个序列号是按照时间顺序递增的。这使得Stream类型非常适合用于实现消息队列、事件驱动的系统、数据流处理等场景。 Stream的底层结构 Redis Stream的底层结构主要由基数树(Radix Tree)和Listpack组成。基数树用于索引Listpack,而Listpack用于存储Stream Entry。每个Stream Ent

By Zhewen Cao
MQTT协议帧结构解析

MQTT协议帧结构解析

MQTT(Message Queuing Telemetry Transport)是一种基于发布/订阅模式的轻量级消息传输协议,广泛应用于物联网(IoT)、移动应用等领域。MQTT的报文帧结构是其通信的基础,主要由三部分组成:固定报头(Fixed Header)、可变报头(Variable Header)和有效载荷(Payload)。以下是对这三部分的详细解析: 1. 固定报头(Fixed Header) 固定报头是MQTT报文帧的开始部分,每个MQTT报文都必须包含固定报头。它占据报文帧的前两个字节,具体结构如下: * 报文类型(4位):第一个字节的前4位(7-4位)用于标识报文类型,MQTT协议定义了16种报文类型,但并非所有类型都已被使用或定义。常见的报文类型包括CONNECT(连接服务器)、CONNACK(连接确认)、PUBLISH(发布消息)、PUBACK(发布确认)、SUBSCRIBE(订阅主题)、SUBACK(订阅确认)等。 * 标志位(

By Zhewen Cao