有了InnoDB,Memory存储引擎还有意义吗?(下)

简介: 两个group by 语句都用了order by null,为什么使用内存临时表得到的语句结果里,0这个值在最后一行;而使用磁盘临时表得到的结果里,0这个值在第一行?

查询对比

  • 优化器选择B-Tree索引,返回结果:0~4

image.png

  • force index 主键id索引,id=0这行在结果集末尾

image.png

我们都觉得内存表优势是速度快,因为Memory引擎支持hash索引。更重要的原因是,内存表的所有数据都保存在内存,内存读写速度肯定比磁盘快。


但仍然不推荐在生产环境上使用内存表,因为有如下严重问题:

内存表的锁

内存表不支持行锁,只支持表锁。因此,一张表只要有更新,就会堵住其他所有在这个表上的读写。

这里的表锁和MDL锁不同,但都是表级锁。

模拟内存表的表级锁

image.png

  • sessionA的update语句要执行50s
  • 该语句执行期间sessionB的查询会进入锁等待状态
  • session C的show processlist:
mysql> show processlist;
+----+-----------------+-----------------+-----------------+---------+--------+------------------------------+---------------------------------------+
| Id | User            | Host            | db              | Command | Time   | State                        | Info                                  |
+----+-----------------+-----------------+-----------------+---------+--------+------------------------------+---------------------------------------+
|  5 | event_scheduler | localhost       | NULL            | Daemon  | 390719 | Waiting on empty queue       | NULL                                  |
| 41 | root            | localhost       | common_mistakes | Query   |      8 | User sleep                   | update t1 set id=sleep(10) where id=1 |
| 47 | root            | localhost       | common_mistakes | Query   |      4 | Waiting for table level lock | select * from t1 where id=2           |
| 49 | root            | localhost:56378 | common_mistakes | Sleep   |    100 |                              | NULL                                  |
| 51 | root            | localhost       | NULL            | Query   |      0 | starting                     | show processlist                      |
+----+-----------------+-----------------+-----------------+---------+--------+------------------------------+---------------------------------------+
5 rows in set (0.00 sec)


表锁限制了并发访问。所以,内存表的锁粒度问题,决定了它在处理并发事务时,性能也不好。

数据持久性

数据放在内存中,是内存表优势,但也是劣势。数据库重启时,所有内存表会被清空。

若数据库异常重启,内存表被清空也就清空了,好像也不会有啥问题呀!但在高可用架构下,内存表的这个特点就是个bug!

M-S架构下内存表的问题。

  • M-S基本架构

image.png

  1. 业务正常访问主库
  2. 备库由于xxx而重启,内存表t1内容被清空
  3. 备库重启后,客户端发送一条update语句,修改t1的数据行,这时备库应用线程就会报错“找不到要更新的行”


这就会导致主备同步停止。当然了,若此时发生主备切换,客户端会看到,t1的数据“丢失”了。

在有proxy的架构,默认主备切换的逻辑由数据库系统自己维护。这样对客户端来说,就是“网络断开,重连之后,发现内存表数据丢失了”。


这也还好呀,毕竟主备发生切换,连接会断开,业务端能够感知到异常!

但接下来内存表会让现象更“诡异”。由于MySQL知道重启之后,会丢失内存表数据。所以,担心主库重启之后,出现主备不一致,MySQL会在数据库重启后,往binlog写一行DELETE FROM t1。

此时若使用的双M架构:


image.pngimage.png

image.png

备库重启时,备库binlog里的delete语句就会传到主库,然后把主库内存表删除。这样你在使用时,就会发现主库的内存表数据突然被清空。


综上,内存表不适合在生产环境使用。


但内存表执行速度就是快呀?!


  • 若你的表更新量大,那么并发度是个重要指标,InnoDB支持行锁,并发度就是比内存表好
  • 能放到内存表的数据量都不大。若你考虑的是读性能,一个读QPS很高 && 数据量不大的表,即使用InnoDB,数据也都会缓存在 Buffer Pool,读性能也不会差!


所以,推荐普通内存表都用InnoDB表替代。

but!有个场景是例外:用户临时表,在数据量可控,不会耗费过多内存的情况下,你可以考虑使用内存表。


内存临时表刚好可以无视内存表的两个不足,主要因为:


  1. 临时表不会被其他线程访问,无并发问题
  2. 临时表重启后也需要删除,不存在清空数据问题
  3. 备库的临时表也不会影响主库的用户线程


看看join语句优化案例,推荐创建一个InnoDB临时表,使用的语句序列是:

create temporary table temp_t
(
    id int primary key,
    a  int,
    b  int,
    index (b)
) engine = innodb;
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);

这里使用内存临时表的效果更好:


  • 使用内存表不需要写磁盘,往表temp_t的写数据的速度更快
  • 索引b使用hash索引,查找的速度比B-Tree索引快
  • 临时表数据只有2000行,占用的内存有限


因此,可以将临时表temp_t改成内存临时表,并且在字段b上创建一个hash索引。

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);
  • 使用内存临时表的执行效果

image.png

不论是导入数据的时间,还是执行join的时间,使用内存临时表的速度都比使用InnoDB临时表要快。

目录
相关文章
|
存储 缓存 关系型数据库
都说InnoDB好,那还要不要使用Memory引擎?
【11月更文挑战第16天】本文介绍了 MySQL 中 InnoDB 和 Memory 两种存储引擎的特点及适用场景。InnoDB 支持事务、外键约束,数据持久性强,适合 OLTP 场景;而 Memory 引擎数据存储于内存,读写速度快但易失,适用于临时数据或缓存。选择时需考虑性能、数据持久性、一致性和完整性需求以及应用场景的临时性和可恢复性。
516 6
|
存储 缓存 关系型数据库
【MySQL进阶篇】存储引擎(MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案)
MySQL的存储引擎是其核心组件之一,负责数据的存储、索引和检索。不同的存储引擎具有不同的功能和特性,可以根据业务需求 选择合适的引擎。本文详细介绍了MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案。
2571 57
【MySQL进阶篇】存储引擎(MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案)
|
存储 关系型数据库 MySQL
MySQL存储引擎详述:InnoDB为何胜出?
MySQL 是最流行的开源关系型数据库之一,其存储引擎设计是其高效灵活的关键。InnoDB 作为默认存储引擎,支持事务、行级锁和外键约束,适用于高并发读写和数据完整性要求高的场景;而 MyISAM 不支持事务,适合读密集且对事务要求不高的应用。根据不同需求选择合适的存储引擎至关重要,官方推荐大多数场景使用 InnoDB。
912 7
|
存储 关系型数据库 MySQL
数据库引擎之InnoDB存储引擎
【10月更文挑战第29天】InnoDB存储引擎以其强大的事务处理能力、高效的索引结构、灵活的锁机制和良好的性能优化特性,成为了MySQL中最受欢迎的存储引擎之一。在实际应用中,根据具体的业务需求和性能要求,合理地使用和优化InnoDB存储引擎,可以有效地提高数据库系统的性能和可靠性。
370 5
|
存储 Oracle 关系型数据库
【赵渝强老师】MySQL的InnoDB存储引擎
InnoDB是MySQL的默认存储引擎,广泛应用于互联网公司。它支持事务、行级锁、外键和高效处理大量数据。InnoDB的主要特性包括解决不可重复读和幻读问题、高并发度、B+树索引等。其存储结构分为逻辑和物理两部分,内存结构类似Oracle的SGA和PGA,线程结构包括主线程、I/O线程和其他辅助线程。
416 0
【赵渝强老师】MySQL的InnoDB存储引擎
|
存储 SQL 缓存
InnoDB 存储引擎以及三种日志
InnoDB 存储引擎以及三种日志
360 0
|
存储 算法 关系型数据库
【MySQL技术内幕】5.7- InnoDB存储引擎中的哈希算法
【MySQL技术内幕】5.7- InnoDB存储引擎中的哈希算法
257 1
|
存储 关系型数据库 MySQL
MySQL InnoDB存储引擎的优点有哪些?
上述提到的特性和优势使得InnoDB引擎非常适合那些要求高可靠性、高性能和事务支持的场景。在使用MySQL进行数据管理时,InnoDB通常是优先考虑的存储引擎选项。
638 0
|
存储 关系型数据库 MySQL
【MySQL技术内幕】5.1-InnoDB存储引擎索引概述
【MySQL技术内幕】5.1-InnoDB存储引擎索引概述
236 0
|
存储 缓存 关系型数据库
【MySQL技术内幕】3.6-InnoDB存储引擎文件
【MySQL技术内幕】3.6-InnoDB存储引擎文件
409 0