MySQL45讲 第38讲 都说InnoDB好,那还要不要使用Memory引擎?——阅读总结

MySQL45讲 第38讲 都说InnoDB好,那还要不要使用Memory引擎?——阅读总结

一、引言

在 MySQL 数据库的世界里,InnoDB 引擎因其诸多优良特性而备受青睐。然而,Memory 引擎也以其独特的优势吸引着人们的目光。那么,在实际应用中,既然 InnoDB 如此出色,我们是否还需要使用 Memory 引擎呢?


二、内存表与 InnoDB 表数据组织结构对比

(一)InnoDB 引擎

InnoDB 采用索引组织表(Index Organizied Table)方式,数据存放在主键索引树上,主键索引是 B + 树结构。

在这里插入图片描述

这使得数据在存储时自然有序,例如在执行 “select * from t2;”(假设 t2 为 InnoDB 表)时,会按照叶子节点从左到右扫描,所以如果主键值为 0 的数据存在,它会出现在结果集的第一行。

在这里插入图片描述

(二)Memory 引擎

Memory 引擎则是堆组织表(Heap Organizied Table)的数据组织形式,数据单独存放,主键 id 索引中保存的是每个数据的位置,其主键 id 为 hash 索引,key 无序。当执行 “select * from t1;”(假设 t1 为 Memory 表)时,走全表扫描,即顺序扫描数据数组,因此 0 会在最后被读到并放入结果集。

在这里插入图片描述

在这里插入图片描述

如果使用范围查询,select * from t1 where id<5;因为主键索引是哈希,所以会全表扫描。

在这里插入图片描述

(三)B-Tree 索引对内存表的影响

内存表虽然主键索引是 hash 索引,但也支持 B-Tree 索引。例如,在表 t1 的alter table t1 add index a_btree_index using btree (id); id 列上创建 B-Tree 索引后,

在这里插入图片描述

执行 select * from t1 where id<5; 时,优化器会选择 B-Tree 索引,返回结果为 0 到 4。

在这里插入图片描述

而使用 force index (primary) 强行使用主键 id 索引时,id = 0 这一行就在结果集的最末尾,这表明 B-Tree 索引使内存表在特定查询下能实现有序返回结果,但与 InnoDB 的 B + 树索引在查询性能和数据组织上仍存在差异。


不建议在生产环境上使用内存表。这里的原因主要包括 两个方面: 1. 锁粒度问题; 2. 数据持久化问题。

三、内存表的锁机制及其影响

(一)锁类型

内存表不支持行锁,仅支持表锁。这意味着只要有一个更新操作在执行,就会阻塞其他所有对该表的**任何读写操作。**例如,在下图的场景中,session A 执行 update t1 set id = sleep (50) where id=1; 时,session B 执行 select * from t1 where id=2; 会进入锁等待状态,直到 session A 的更新操作完成。

在这里插入图片描述

(二)与 MDL 锁的区别

需要注意的是,这里的表锁与之前介绍的 MDL 锁虽然都是表级锁,但有所不同。MDL 锁主要用于控制对表结构的修改等操作,而内存表的表锁则针对数据的读写操作。

(三)对并发性能的影响

**与 InnoDB 支持行锁相比,内存表的表锁在处理并发事务时性能较差。**在高并发场景下,InnoDB 能够更细粒度地控制锁,允许多个事务同时对不同行进行读写操作,从而提高系统的整体并发性能。


四、内存表的数据持久性问题

(一)数据库重启对内存表的影响

内存表的数据存放在内存中,这一特性在数据库重启时会导致所有内存表被清空。在高可用架构下,这可能引发一系列问题。例如,在 M - S 架构中,若**备库硬件升级重启,内存表 t1 内容被清空,之后客户端发送更新语句修改表 t1 数据行时,备库应用线程会报错 “找不到要更新的行”,进而导致主备同步停止。**若此时发生主备切换,客户端会发现表 t1 的数据 “丢失”。

(二)双 M 结构中的特殊情况

在双 M 结构中,情况更为复杂。**由于 MySQL 担心主库重启后出现主备不一致,在数据库重启后会往 binlog 写入 “DELETE FROM t1”。**当备库重启时,备库 binlog 里的 delete 语句会传到主库,导致主库内存表内容被删除,使得主库内存表数据突然清空,这对业务的影响更加难以预测和控制。


五、InnoDB 与 Memory 引擎的适用场景分析

(一)InnoDB 引擎的优势与适用场景

  1. 数据安全与并发性能
    InnoDB 支持行锁,在高并发场景下能够提供更好的并发性能,同时其数据持久性较好,适合处理大量更新操作和对数据一致性要求较高的业务场景。
  2. 读性能优化
    即使是读操作较多且数据量不大的表,使用 InnoDB 也能通过其 Buffer Pool 将数据缓存到内存中,从而获得不错的读性能。

(二)Memory 引擎的适用场景 - 内存临时表

  1. 无并发问题
    内存临时表不会被其他线程访问,不存在并发性问题,因此在复杂查询的优化过程中,如分库分表系统的跨库查询中,可用于暂存中间数据。
  2. 数据可清空
    临时表在重启后需要删除数据,这与内存表重启清空数据的特性相契合,不会产生额外的数据管理问题。
  3. 不影响主库用户线程
    在主备架构中,备库的临时表不会影响主库的用户线程,保证了系统的正常运行。

(三)内存临时表的优化示例

在第 35 篇 join 语句优化的例子中,使用内存临时表效果更好。如将临时表改为内存临时表并在字段 b 上创建 hash 索引后,导入数据和执行 join 的速度都比使用 InnoDB 临时表更快。具体操作如下:

create temporary table temp_t(id int primary key, a int, b int, index (b))engine=memory;
insert into temp_t select * from t2 where b>=1 and b<=2000;
select * from t1 join temp_t on (t1.b=temp_t.b);

六、总结

综上所述,在生产环境中,一般不建议使用普通内存表作为常规数据表,因其存在锁粒度粗和数据持久性差等问题。而 InnoDB 引擎在数据安全和并发性能方面表现出色,适用于大多数业务场景。但内存临时表利用了 Memory 引擎的特性,在特定场景下能够发挥重要作用,如复杂查询中的临时数据存储和加速查询执行等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KELLENSHAW

相信过程

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值