Hi~朋友,关注置顶防止错过消息
create table t1(id int primary key, c int) engine=Memory;create table t2(id int primary key, c int) engine=innodb;insert into t1 values(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9),(0,0);insert into t2 values(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9),(0,0);

数据的组织方式
Memory引擎的表和InnoDB引擎的表我们在执行全表查询的时候,Mmeory引擎的表返回结果0在最后一行,而InnoDB引擎的表0在第一行。这种区别主要是因为数据组织方式的不同。
InnoDB引擎索引的组织方式是B+树,是有序存储,在执行select *的时候会从主键索引的叶子节点从左到右扫描,所以0出现在第一行。
Memory引擎的数据和索引是分开的,表的数据部分以数组的方式单独存放,而主键索引中存的是每个数据的位置,且主键id是hash索引,因此在主键索引上的key并不是有序的,当select *会走全表扫描,顺序扫描存放数据的数组,因此0出现在了最后一行。
InnoDB和Memory引擎的数据组织方式
InnoDB引擎把数据存储在主键索引上,其他索引上保存的是主键id,该方式称之为索引组织表 Memory引擎把数据单独存放,索引上保存的是数据的位置,该方式称之为堆组织表
InnodDB引擎和Memory引擎的不同
InnoDB数据总是有序存放,Memory引擎表的数据是按照写入顺序存放 数据文件有空洞时,InnoDB表在插入新数据时为保证有序性,只能在固定的位置写入新值,但是Memory表找到空位就可以插入新值 数据位置发生变更时,InnoDB表只需要修改主键索引,Memory表需要修改所有索引 InnoDB表普通索引需要走两次索引查找,Memory表普通索引只走一次和主键索引没有什么区别 InnoDB支持变长数据类型,Memory表不支持Blob和Text字段,并且即使定义了VARCHAR(N),也会被当做CHAR(N)
Memory表也支持Hash索引和B-Tree索引,语句如下:
alter table t1 add index a_btree_index using btree (id);alter table t1 add index a_btree_index using hash (id);
Memory表的锁
Memory表不支持行锁,支持表锁。
| Session A | Session B | Session C |
|---|---|---|
| update t1 set id = sleep(50) where id = 1; | ||
| select * from t1 where id = 2; | ||
| show processlist; |

可以看出Memory表的锁粒度过大,在处理并发事务时性能较低。
Memory的数据持久性问题
Memory表的数据存放在内存中,如果数据库重启,表中的数据将会被清除,单点下并没有什么问题,但如果在高可用的架构下将会出现问题。
M-S架构下的Memory表的问题
业务正常访问Master库 备库硬件升级需要重启,重启以后,内存表的数据会被清空 备库重启后,主库上有一条update语句需要修改t1的数据行,修改表t1的数据行在传到备库时无法知道要更新的行 假设恰巧此时发生主备切换,客户端会发现Memory表的数据丢失了。
由于MySQL知道重启后内存表数据会丢失,所以在担心主库重启后,出现主备不一致,MySQL会在数据库重启以后往binlog中写一条TRUNCATE TABLE 库名.memeory表名。

如果你是双M架构,在备库重启的时候,上面的SQL语句会被传递主库执行,然后把主库Memory表的内容也清空了。
本期MySQL Memory引擎就到这,扫码关注,更多内容我们下期再见!

文章转载自程序员修炼笔记,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




