笔记 笔记
首页
  • 开发工具
  • Java Web
  • Java 进阶
  • 容器化技术
  • Java 专栏

    • Java 核心技术面试精讲
    • Java 业务开发常见错误 100 例
  • 数据库专栏

    • MySQL 实战 45 讲
    • Redis 核心技术与实战
  • 安全专栏

    • OAuth 2.0 实战课
  • 计算机系统
  • 程序设计语言
  • 数据结构
  • 知识产权
  • 数据库
  • 面向对象
  • UML
  • 设计模式
  • 操作系统
  • 结构化开发
  • 软件工程
  • 计算机网络
  • 上午题错题
在线工具 (opens new window)

EasT-Duan

Java 开发
首页
  • 开发工具
  • Java Web
  • Java 进阶
  • 容器化技术
  • Java 专栏

    • Java 核心技术面试精讲
    • Java 业务开发常见错误 100 例
  • 数据库专栏

    • MySQL 实战 45 讲
    • Redis 核心技术与实战
  • 安全专栏

    • OAuth 2.0 实战课
  • 计算机系统
  • 程序设计语言
  • 数据结构
  • 知识产权
  • 数据库
  • 面向对象
  • UML
  • 设计模式
  • 操作系统
  • 结构化开发
  • 软件工程
  • 计算机网络
  • 上午题错题
在线工具 (opens new window)

购买兑换码请添加

添加时候请写好备注,否则无法通过。

  • 38-都说InnoDB好,那还要不要使用Memory引擎?

    • 内存表的数据组织结构
      • hash 索引和 B-Tree 索引
        • 内存表的锁
          • 持久性问题
          EasT-Duan
          2024-04-07
          随笔
          目录

          38-都说InnoDB好,那还要不要使用Memory引擎?

          欢迎来到我的 ChatGPT 中转站,极具性价比,为付费不方便的朋友提供便利,有需求的可以添加左侧 QQ 二维码,另外,邀请新用户能获取余额哦!最后说一句,那啥:请自觉遵守《生成式人工智能服务管理暂行办法》。

          正文

          # 内存表的数据组织结构

          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);
          
          1
          2
          3
          4

          t1 的 (0,0) 在最后一行,而 t2 (0,0) 在第一行。这是因为 InnoDB 主键索引上的存储的数据值是有序的。但是 Memory 的数据和索引是分开的,Memory 主键是 hash 索引并且上面存储的是值的位置。

          笔记

          两者的不同

          • InnoDB 引擎把数据放在主键索引上,其他索引上保存的是主键 id。这种方式,称为索引组织表(Index Organizied Table)。
          • Memory 引擎采用的是把数据单独存放,索引上保存数据位置的数据组织形式,称为堆组织表(Heap Organizied Table)。
          • InnoDB 存放的数据总是有序的,而 Memory 是按照写入顺序来存放的。
          • 当数据文件有空洞时候,InnoDB 插入新的数据,为了保证顺序性只能在固定位置插入,而 Memory 会找到空洞位置插入。
          • 数据位置发生变化的,InnoDB 只用修改主键索引,Memory 需要修改所有索引。
          • InnoDB 使用主键索引走一次索引查询,普通索引走两次索引查询,Memory 没有这个说法,所有的索引都是相同 “地位”。
          • InnoDB 支持变长数据类型,不同记录的长度可能不同;内存表不支持 Blob 和 Text 字段,并且即使定义了 varchar (N),实际也当作 char (N),也就是固定长度字符串来存储,因此内存表的每行数据长度相同。

          # hash 索引和 B-Tree 索引

          内存表也是可以用使用 B-Tree 索引的。通过下面语句将 t1 改成 b 树。

          alter table t1 add index a_btree_index using btree (id);
          
          1

          执行这两个查询语句可以发现,第一条使用了 b 树索引返回了 0、1、2、3、4,第二个强制使用了主键索引结果为 1、2、3、4、0。

          注意

          这里要弄清楚一个概念,memory 表的默认索引类型为 hash 索引。

          alter table t1 add index a_btree_index using btree (id);
          
          1

          这条语句表示你为 'id' 字段添加了一个名为 'a_btree_index' 的 B-Tree 索引。但是这并没有改变仍存在的主键的哈希索引。只是意味着,当查询可以选择时(不强制使用特定索引),它可以选择使用你新添加的 B-Tree 索引。但是强制使用了主键索引后,就还是用到了 hash 索引类型,所以读取顺序就和写入顺序一致。

          select * from t1 where id < 5;
          select * from t1 force index(primary) where id < 5;
          
          1
          2

          虽然看起来 memory 表很多好处,但是还是不建议在生产环境使用。主要有两个问题

          1. 锁粒度问题;
          2. 数据持久化问题。

          # 内存表的锁

          内存表不支持行锁,只支持表锁。这就意味着一旦有更新就会锁住整个表。如果存在并发问题,这个总体效果很差,会明显不如 innodb,更不用说如果有长事务了。

          # 持久性问题

          数据库重启的时候会把内存表中的数据清空。在主从架构下,这就是一个 bug 了。看这个流程

          • 业务正常访问主库。
          • 备库升级,重启,内存表 t 被清空。
          • 客户端更新 t 的数据,备库线程会报错 “找不到更新的行”。

          这是其一,其二是由于 MySQL 知道重启之后,内存表的数据会丢失。所以,担心主库重启之后,出现主备不一致,MySQL 在实现上做了这样一件事儿:在备库重启的时候就传了这条语句到主库,导致主库的内容也没了。

          但是还是有些情况可以用的,比如之前说的 join 的时候如果没办法用到索引,就可以用到临时表将一部分数据放进去然后再与临时表进行 join。

          #MySQL
          上次更新: 2025/04/12, 05:37:39
          最近更新
          01
          Reactor 核心
          02-24
          02
          前置条件
          10-30
          03
          计算机网络
          09-13
          更多文章>
          Theme by Vdoing | Copyright © 2019-2025 powered by Vdoing
          • 跟随系统
          • 浅色模式
          • 深色模式
          • 阅读模式