内存表
内存表,指的是使用Memory引擎的表,建表语法是create table … engine=memory。这种表的数据都保存在内存里,系统重启的时候会被清空,但是表结构还在。
临时表
临时表,可以使用各种引擎类型。如果是使用InnoDB引擎或者MyISAM引擎的临时表,写数据的时候是写到磁盘上的。当然,临时表也可以使用Memory引擎。
临时表在使用上有以下几个特点:
-
建表语法是create temporary table …。
-
一个临时表只能被创建它的session访问,对其他线程不可见。
-
临时表可以与普通表同名,不同session的临时表也是可以重名的。
-
同一个会话内有同名的临时表和普通表的时候,show create语句,以及增删改查语句访问的是临时表。
-
show tables命令不显示临时表。
临时表的应用
- 由于不用担心线程之间的重名冲突,临时表经常会被用在复杂查询的优化过程中。
- 分库分表中的一些场景也可以用到 (过程机制以及性能表现个人意见觉得一般 基本指望不上)
为什么临时表可以重名
MySQL要给InnoDB表创建一个frm文件保存表结构定义,还要有地方保存表数据。这个frm文件放在临时文件目录下,文件名的后缀是.frm,前缀是“#sql{进程id}_{线程id}_序列号”。可以使用select @@tmpdir命令,来显示实例的临时文件目录。
表数据的存放方式,在不同的MySQL版本中有着不同的处理方式:
- 在5.6以及之前的版本里,MySQL会在临时文件目录下创建一个相同前缀、以.ibd为后缀的文件,用来存放数据文件;
- 5.7版本开始,MySQL引入了一个临时文件表空间,专门用来存放临时文件的数据。因此,我们就不需要再创建ibd文件了。
MySQL维护数据表,除了物理上要有文件外,内存里面也有一套机制区别不同的表,每个表都对应一个table_def_key。
- 一个普通表的table_def_key的值是由“库名+表名”得到的,所以如果你要在同一个库下创建两个同名的普通表,创建第二个表的过程中就会发现table_def_key已经存在了。
- 对于临时表,table_def_key在“库名+表名”基础上,又加入了“server_id+thread_id”。
实现
- 在实现上,每个线程都维护了自己的临时表链表。
- 每次session内操作表的时候,先遍历链表,检查是否有这个名字的临时表;
- 如果有就优先操作临时表,如果没有再操作普通表;
- 在session结束的时候,对链表里的每个临时表,执行 “DROP TEMPORARY TABLE +表名”操作。(备库同步)
主备同步
MySQL在记录binlog的时候,会把主库执行这个语句的线程id写到binlog中。这样,在备库的应用线程就能够知道执行每个语句的主库线程id,并利用这个线程id来构造临时表的table_def_key:
-
session A的临时表t1,在备库的table_def_key就是:库名+t1+“M的serverid”+“session A的thread_id”;
-
session B的临时表t1,在备库的table_def_key就是 :库名+t1+“M的serverid”+“session B的thread_id”。