暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MYSQL-NOTE30,临时表

kids and edu 2021-08-27
452

临时表和内存表的区别

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。

 


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

评论