-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
Description
示例表
create table t1(id int primary key, c int) engine=Memory;
insert into t1 values(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9),(0,0);
Memory 引擎的数据组织结构
Memory 引擎的数据和索引是分开的,数据部分以数组的方式单独存放,而主键 id 索引存放的是每个数据的位置,而且主键 id 是 hash 索引,索引上的 key 并不是有序的,这种数据组织形式称为堆组织表
Memory 引擎的一些特性:
- 数据安装写入顺序存放
- 当数据文件有空洞的时候,找到空位就可以插入新值
- 数据位置发生变化是,需要修改所有索引
- 使用普通索引查询时,不用走两遍索引
- 不支持 Blob 和 Text,并且即使定义了 varchar(N),也会当作 char(N) 来处理
- 因为主键索引是哈希索引,执行范围查询是需要走全表扫描
hash 索引和 B-Tree 索引
Memory 引擎是支持 B-Tree 索引的,和 InnoDB 的 B+ 树索引组织形式类似
alter table t1 add index a_btree_index using btree (id);
这时,表 t1 的数据组织形式如下:
两种索引的查询结果的区别:
Memory 引擎的锁
Memory 引擎不支持行锁,只支持表锁,一张表只要有更新,就会堵住其他所有在这个表上的读写操作,在并发访问和处理并发事务的时候 ,性能不会太好
数据持久性问题
M-S 结构下,下面这个时序就会出现问题:
- 业务正常访问主库
- 备库硬件升级,备库重启,内存表 t1 内容被清空
- 备库重启后,客户端发送一条 update 语句,修改表 t1 的数据行,这时备库应用线程就会报错 “找不到要更新的行”
这种情况下,业务端能够感知到异常,可能还好处理。
但还有一种情况是在双 M 结构下,由于 MySQL 知道重启之后,内存表的数据会丢失,所以,担心主库重启后,出现主备不一致,会往 binlog 里面写入 DELETE FROM t1 ,造成主库的内存表突然被清空
使用场景
理论上建议把普通内存表都使用 InnoDB 表代替,但在使用用户临时表时,如果数据量可控,可以考虑使用内存表,主要基于以下考虑:
- 临时表不会被其他线程访问,没有并发性问题
- 临时表重启后也是需要删除的,清空数据这个问题不存在
- 备库的临时表也不会影响主库的用户线程
- 内存表不需要写磁盘,写速度更快
- 内存表使用 hash 索引,查询速度更快