临时表为什么可以重名
临时表的一些特性:
1、创建语法:create temporary table
2、只有创建该表的session才可以访问,其他线程无法访问
3、临时表可以与普通表重名
4、session中有同名的临时表和普通表时,操作的都是临时表
临时表应用
在分库分表的场景下,我们现在假设某一个大表ht 按照字段f分为了1024个表,分布在32个数据库上。如下图所示:

这种设计下,如果我们执行如下sql:
1 | select v from ht where f = N; |
因为该sql使用了分表的字段f,那么我们就可以直接找到数据所在的表。
但是如果是如下sql:
1 | select v from ht where k >= M order by t_modified desc limit 100; |
该sql没有使用到分表的字段f,那么只能到所有的分区中去查找满足条件的所有行,然后统一做order by 的操作。
这种情况下,有两种方法:
1、把所有的数据全部查到,然后交给代理层去做排序。这种方法的优点是MySQL查询会很快,但是需要代理层多做额外的处理。
2、把各个分库拿到的数据,汇总到一个MySQL实例的一个表中,然后在这个汇总实例上做逻辑操作。流程如下图:

为什么临时表可以重名?
MySQL维护数据表,除了物理上要有文件外,内存里面也有一套机制区别不同的表,每个表都对应一个table_def_key。
- 一个普通表的table_def_key的值是由“库名+表名”得到的,所以如果你要在同一个库下创建两个同名的普通表,创建第二个表的过程中就会发现table_def_key已经存在了。
- 而对于临时表,table_def_key在“库名+表名”基础上,又加入了“server_id+thread_id”。
也就是说,session A和sessionB创建的两个临时表t1,它们的table_def_key不同,磁盘文件名也不同,因此可以并存。
在实现上,每个线程都维护了自己的临时表链表。这样每次session内操作表的时候,先遍历链表,检查是否有这个名字的临时表,如果有就优先操作临时表,如果没有再操作普通表;在session结束的时候,对链表里的每个临时表,执行 “DROP TEMPORARY TABLE +表名”操作。