内存表与临时表区别
临时表,一般是人手动创建。 内存表,是mysql自动创建和销毁的。
内存表,指的是使用Memory引擎的表,建表语法:create table ... engine = memeory
表的数据存在内存里,系统重启后会被清空,但是表的结构还在。
临时表,可以使用各种引擎类型。如果使用的是InnoDB或者MyISAM引擎,写数据是写在磁盘上的。当然临时表也可以使用Memory引擎。
临时表特性
1、一个临时表只能被创建它的session访问,对于其他线程不可见,当此session结束时,会自动删除临时表
2、临时表可以与普通表同名。如果同一个session里有同名的临时表和普通表,使用show create语句以及增删改查语句,访问的是临时表
3、show tables命令不显示临时表
临时表的应用
由于不用担心线程之间的重名冲突,临时表经常被用在复杂查询的优化过程中。其中,分库分表系统的跨库查询就是一个典型的使用场景。
查询语句到所有的分库中查找满足条件的行,然后统一做order by操作。
可以把各个分库拿到的数据汇总到一个MySQL实例的一个表中,然后在这个汇总实例上做逻辑操作。如下:
至于临时表的存储位置,可以放在分库中的某一个。
另外一个使用场景就是使用union(如果使用的是union all就不需要用了)。系统会先创建一个内部临时表,执行第一个子查询的结果放到临时表中,执行第二个子查询的结果先看看插入是否成功,成功则插入。最后从临时表中按行取数据,然后返回结果,删除临时表。
临时表可以重名的原因
无论是普通表还是临时表,一个表都会对应一个table_def_def
- 一个普通表的
table_def_def
的值由"库名+表名"得到。所以在同一个库下创建两个同名的普通表,会由重复性错误。 - 对于临时表,
table_def_def
在“库名+表名”的基础上还加上了“server_id + thread_id”
在实现上,每个线程都维护了自己的临时表链表,每次session内操作表的时候,先遍历链表,检查是否有这个名字的的临时表,有就优先操作,否则再操作普通表。
session结束时,对链表中的每个临时表,执行drop操作。这个操作也会被写道binlog里用于主备复制。
临时表的主备同步
row格式的binlog不会记录临时表相关语句,只有statement或者mixed格式才会记录。
创建临时表的语句会传到备库执行,因此备库的同步线程就会创建这个临时表。主库在线程退出的时候会自动删除临时表,但是备库同步线程还是在运行的,所以主库还需要写个DROP TEMPORARY TABLE
传给备库。
当主库上两个session创建了同名临时表t1,这两个语句被传给备库上。
主库执行语句的线程id会被写道binlog中,备库可以用线程id构造临时表的table_def_key
:
备库名 + t1 + “主库的serverid” + “session的thread_id”
,所以两个表在备库的应用线程不会冲突。