memory 存储引擎是 mysql 中一种高性能但非持久化的存储方案,适合临时数据存储和缓存场景。其核心优势在于极快的读写速度,需注意数据丢失风险和内存占用限制。
在使用时需结合业务需求,合理配置参数(如max_heap_table_size),并避免将其用于需要持久化或事务支持的场景。
1、memory引擎介绍
mysql memory引擎用于创建内存中的表,数据存储在内存,访问快速但重启后数据丢失。通过--init-file启动mysqld可持久化数据。
内存表默认使用hash索引,适用于临时表,但有限制如不支持blob/text,且所有用户可见。可以利用其速度优势创建内存临时表替代myisam临时表。
数据完全存储在内存中:
- 数据和索引均存在于内存中,无磁盘 i/o 开销。
- 重启 mysql 或异常关闭后,数据会丢失。
存储限制:
- 受max_heap_table_size和tmp_table_size参数限制。
- 不支持大字段(如text、blob)。
存储结构:
- 仅支持哈希索引,适合等值查询(
=
),不支持范围查询(>
、<
、between
)。 - 不支持事务
2、memory内存结构
仅支持哈希索引,数据存放将索引和数据分开存储。
索引采用hash的形式,存放主键id和指向数据的指针,而数据则按插入顺序存放。称这种数据组织方式为堆组织方式。
如下图所示:
特点:且数据的hash的key也不支持有序,value也没指定的顺序。
3、内存表的锁
内存表不支持行锁,只支持表锁。如果一张表有更新,就会堵住其它所有在这个表上的读写操作。导致了memory存储引擎在进行并发操作时会造成大量的阻塞,效率不高。
示例:
在这个执行序列里, session a的update语句要执行50秒, 在这个语句执行期间session b的查询会进入锁等待状态。 session c的show processlist 结果输出如下:
跟行锁比起来, 表锁对并发访问的支持不够好。
4、持久化
如果数据库重启,所有的内存表都会被清空。
在主备场景:
看一下下面这个时序:
- 业务正常访问主库。
- 备库硬件升级, 备库重启, 内存表t1内容被清空。
- 备库重启后, 客户端发送一条update语句, 修改表t1的数据行, 这时备库应用线程就会报错“找不到要更新的行”。
⚠️注意:内存表可能导致主备不一致。
解决方案:
所以, 担心主库重启之后, 出现主备不一致, mysql在实现上做了这样一件事儿: 在数据库重启之后, 往binlog里面写入一行delete from t1。
在备库重启的时候, 备库binlog里的delete语句就会传到主库, 然后把主库内存表的内容删除。这样使用的时候就会发现, 主库的内存表数据突然被清空了。
无论是m-s架构,还是双m架构,内存表都不适合在生产环境上作为普通数据表使用。
5、优缺点
6、应用
设置:
set sql_log_bin=off; alter table tbl_name engine=innodb;
假设有以下两张表t1、t2,其中表t1是memory引擎,表t2是innodb引擎。
-- 创建表t1,t2,分别使用memory引擎和innodb引擎; create table t1(id int primary key,c int) engine=memory; create table t2(id int primary key,c int) engine=innodb; insert into t1values(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9),(0,0); insert into t2values(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9),(0,0); -- 执行查询语句,得到结果如下图: select * from t1; select * from t2;
结果如下:
根据图示可知:
内存表t1的返回结果里面0在最后一行, 而innodb表t2的返回结果里0在第一行。
表t1是memory表,而memory表的数据和索引是分开的。
数据组织方式如下:
由上可知,内存表的数据部分以数组的方式单独存放,而主键id索引里,存的是每个数据的位置。主键id是hash索引,可以看到索引上的key并不是有序的。
在对表t1执行select *的时候, 走的是全表扫描, 也就是顺序扫描这个数组。 因此, 0就是最后一个被读到, 并放入结果集的数据。
表t2是innodb表,其数据就放在主键索引树上,主键索引是b+树。
数据组织方式如下:
主键索引上的值是有序存储的,在执行select *的时候, 就会按照叶子节点从左到右扫描, 所以得到的结果里, 0就出现在第一行。
关于三种不同引擎的总结
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论