临时表和内存表的区别
1)内存表,指的是使用 Memory 引擎的表,建表语法是 create table … engine=memory。这种表的数据都保存在内存里,系统重启的时候会被清空,但是表结构还在。
2)临时表,可以使用各种引擎类型 。如果是使用 InnoDB 引擎或者 MyISAM 引擎的临时表,写数据的时候是写到磁盘上的。临时表也可以使用 Memory 引擎。
临时表几个特点:
1)建表语法是 create temporary table
2)临时表只能被创建它的 session 访问,对其他线程不可见。Session结束自动删除。
3)临时表可以与普通表同名。
4)session内有同名的临时表和普通表的时候,show create 语句,以及增删改查语句访问的是临时表。
5)show tables 命令不显示临时表。
临时表的应用
不会导致线程之间的重名冲突,临时表经常会被用在复杂查询的优化过程中。其中,分库分表系统的跨库查询就是一个典型的使用场景。
如果查询条件里面没有用到分区字段,只能到所有的分区中去查找满足条件的所有行,然后统一做操作(如排序)
第一种思路是,在 proxy 层的进程代码中实现排序
优势:处理速度快,拿到分库的数据以后,直接在内存中参与计算。
缺点:
1)需要的开发工作量比较大,对中间层的开发能力要求比较高;
2)对 proxy 端的压力比较大,尤其是很容易出现内存不够用和 CPU 瓶颈的问题。
另一种思路就是,把各个分库拿到的数据,汇总到一个 MySQL 实例的一个表中,然后在这个汇总实例上做逻辑操作。
1)在汇总库上创建一个临时表 temp_ht(这个汇总库可以是N个分库中的某一个)
2)在分库上执行
3)把分库结果插入到汇总库的临时表里面
4)从临时表里面查数据
为什么临时表可以重名?
create temporary table temp_t(id int primary key)engine=innodb;
MySQL 要给这个 InnoDB 表创建一个 frm 文件保存表结构定义,还要有地方保存表数据。这个 frm 文件放在临时文件目录下,文件名的后缀是.frm,前缀是“#sql{进程 id}_{线程 id}_ 序列号”
数据存放:
1)5.6 以及之前的版本里,MySQL 会在临时文件目录下创建一个相同前缀、以.ibd 为后缀的文件,放数据文件;
2)5.7 版本之后,MySQL 引入了一个临时文件表空间,专门用来存放临时文件的数据。不需要再创建 ibd 文件了。
MySQL 维护数据表,除了物理上要有文件外,内存里面也有一套机制区别不同的表,每个表都对应一个 table_def_key
1)一个普通表的 table_def_key 的值是由“库名 + 表名”得到的,创建第二个表会提示 table_def_key 已经存在;
2)而对于临时表的table_def_key 在“库名 + 表名”基础上,又加入了“server_id+thread_id”。
每个线程都维护了自己的临时表链表。
1)session 内操作表的时候,先遍历链表,检查是否有这个名字的临时表,如果有就优先操作临时表,如果没有再操作普通表;
2)在 session 结束的时候,对链表里的每个临时表,执行 “DROP TEMPORARY TABLE + 表名”操作。
binlog 中也记录了 DROP TEMPORARY TABLE 这条命令
为什么需要记binlog呢,binlog,就意味着备库需要。
1)如果当前的 binlog_format=row,那么跟临时表有关的语句,就不会记录到 binlog 里。
2)binlog_format=statment/mixed 的时候,binlog 中才会记录临时表的操作。
MySQL 在记录 binlog 的时候,会把主库线程 id 写到 binlog 中。
这样,在备库的应用线程就能够知道执行每个语句的主库线程 id,并利用主库线程 id 来构造临时表的 table_def_key。




