【澳门金沙vip】MySQL如何创建和删除临时表

 

FLUSH TABLE WITH READ LOCK详解,flushlock

      FLUSH TABLES WITH READ
LOCK简称(FTWEscortL),该命令主要用于备份工具获得一致性备份(数据与binlog位点相称)。由于FTWRubiconL总共必要全数两把全局的MDL锁,并且还亟需关闭全部表对象,因而那些命令的杀伤性相当的大,实行命令时便于导致库hang住。借使是主库,则业务不可能日常访问;假若是备库,则会招致SQL线程卡住,主备延迟。本文将详细介绍FTWKoleosL到底做了什么操作,各种操作的对库的熏陶,以及操作背后的缘故。 

FTW奥迪Q7L做了何等操作?

FTW帕杰罗L紧要包罗3个步骤:

1.上全局读锁(lock_global_read_lock)
2.清理表缓存(close_cached_tables)
3.上全局COMMIT锁(make_global_read_lock_block_commit)

FTWCR-VL每一个操作的影响

   
 上全局读锁会导致全体更新操作都会被堵塞;关闭表经过中,假如有大查询导致关闭表等待,那么全体访问那一个表的询问和换代都亟待等待;上全局COMMIT锁时,会杜绝活跃事务提交。由于FTW哈弗L主要被备份工具使用,前边会详细解释每一个步骤的成效,以及存在的要求性。FTW牧马人L中的第1和第3步都是因而MDL锁实现,关于MDL的达成,作者事先总计了MDL锁的小说,这里根本介绍清理表缓存的流程。 

理清表缓存   

  
 每一种表在内部存款和储蓄器中都有三个table_cache,分歧表的cache对象通过hash链表维护。

访问cache对象通过LOCK_open互斥量爱慕,每一种会话展开的表时,引用计数share->ref_count++,
关闭表时,都会去对引用计数share->ref_count–。

若觉察是share对象的末尾一个引用(share->ref_count==0),并且share有old_version,

则将table_def_cache从hash链表中摘除,调用free_table_share实行管理。关键函数close
table流程如下:

1.闭馆全数未利用的表对象
2.更新全局字典的版本号
3.对于在行使的表对象,逐一检查,若表还在动用中,调用MDL_wait::timed_wait举行等待
4.将等待对象关联到table_cache对象中
5.接续遍历使用的表对象
6.直到全部表都不再使用,则关闭成功。

清理表缓存函数调用

mysql_execute_command->reload_acl_and_cache->close_cached_tables

->TABLE_SHARE::wait_for_old_version->MDL_wait::timed_wait->
inline_mysql_cond_timedwait

对话操作表流程

1.张开表操作,若觉察还会有old_version,则张开等待
2.share->ref_count++
3.操作结束,检查share->ref_count–是否为0
4.若为0,并且检查发掘有新本子号,则感到cache对象供给重载
5.将cache对象摘除,调用MDL_wait::set_status唤醒全部等待的线程。

关闭表对象函数调用

dispatch_command->mysql_parse->mysql_execute_command->

close_thread_tables->close_open_tables->close_thread_table->

intern_close_table->closefrm->release_table_share->my_hash_delete->
table_def_free_entry->free_table_share

关闭表导致业务库堵住的独领风流气象

   
 借使有3个会话,会话A实行大查询,访问t表;然后二个备份会话B正处在关闭表阶段,需求关闭表t;随后会话C也呼吁访问t表。八个会话依据这么些顺序实践,大家会开采备份会话B和会话C访问t表的线程都地处“waiting
for table
flush”状态。那正是停业表引起的,这些主题材料十分惨重,因为那时候一般的select查询也被阻挡了。上边轻便表达下原因:

1.会话A打开表t,执行中……
2.备份会话B需求清理表t的cache,更新版本号(refresh_version++)
3.会话B开采表t存在旧版本(version !=
refresh_version),表示还大概有会话正在访问表t,
等候,插足share对象的守候队列
4.持续会话C同样开采存在旧版本(version != refresh_version),
等候,插足share对象的守候队列
……

  1. 大查询实践实现,调用free_table_share,唤醒全数等待线程。

free_table_share //逐一唤醒全部等待的线程。
{
while ((ticket= it++))
ticket->get_ctx()->m_wait.set_status(MDL_wait::GRANTED);
}

第4步与第5步之间,全部的造访该表的对话都处于“waiting for table
flush”状态,唯有大查询停止后,等待状态本领排除。

主备切换场景

     
在生养条件中,为了容灾一般mysql服务都由主备库组成,当主库出现难题时,能够切换成备库运营,保证服务的高可用。在那一个历程中有点很要紧,制止双写。因为导致切换的风貌有这几个,恐怕是因为主库压力过大hang住了,也许有望是主库触发mysql
bug重启了等。当我们将备库写开启时,如若老主库活着,一定要先将其安装为read_only状态。“set
global
read_only=1”那个命令实际上也和FTW奥迪Q7L类似,也须要上两把MDL,只是无需清理表缓存而已。假诺老主库上还恐怕有大的更新专业,将导致set
global read_only hang住,设置战败。因而切换程序在规划时,要怀想那或多或少。

重中之重函数:fix_read_only

1.lock_global_read_lock(),制止新的翻新职业,阻止更新操作
2.make_global_read_lock_block_commit,制止活跃的事情提交

FTWRL与备份

     
Mysql的备份方式,首要总结两类,逻辑备份和大体备份,逻辑备份的经典代表是mysqldump,物理备份的卓著代表是extrabackup。依据备份是或不是须要结束服务,能够将备份分为冷备和热备。冷备要求服务器关闭,这么些在生育情状中基本不现实,而且也与FTWRubiconL非亲非故,这里根本钻探热备。Mysql的框架结构辅助插件式存款和储蓄引擎,平日我们以是或不是帮衬职业划分,标准的代表就是myisam和innodb,那多个存款和储蓄引擎分别是前期和当今mysql表的私下认可存款和储蓄引擎。大家的座谈也根本围绕这三种引擎张开。对于innodb存款和储蓄引擎来讲,在采纳mysqldump获取一致性备份时,大家平时会接纳四个参数,–single-transaction和–master-data,前者保险innodb表的数目一致性,后者保障收获与数据备份匹配的一致性位点,主要用来搭建复制。未来利用mysql主备集群基本是标配,所以也是需要的。对于myisam,就供给经过–lock-all-tables参数和–master-data来完结同等的目标。大家在来回想下FTW翼虎L的3个步骤:

  1. 上全局读锁
  2. 理清表缓存
  3. 上全局COMMIT锁

率先步的意义是杜绝更新,备份时,大家希望获得此时数据库的同等状态,不指望有更加多的换代操作进来。对于innodb引擎来说,其自己的MVCC机制,能够确定保证读到老版本数据,因而首先步对它使多余的。第二步,清理表缓存,那一个操作对于myisam有含义,关闭myisam表时,会强制供给表的缓存落盘,那对于物理备份myisam表是有含义的,因为物理备份是一向拷贝物理文件。对于innodb表,则不必要那样,因为innodb有和好的redolog,只要记下当时LSN,然后备份LSN今后的redolog就可以。第三步,首要是保障能获得一致性的binlog位点,那点对于myisam和innodb作用是同等的。

   
 所以总的来讲,FTW科雷傲L对于innodb引擎来说,最根本的是收获一致性位点,前边多个步骤是卑不足道的,因而假使业务表全都是innodb表,那把大锁从常理上来说是足以拆的,而且percona集团也确确实实做了那样的政工,具体咱们可以参照他事他说加以考查blog链接。其余,官方版本的5.5和5.6对于mysqldump做了四个优化,首要改造是,5.5备份一个表,锁二个表,备份下三个表时,再上锁四个表,已经备份完的表锁不自由,那样持续开始展览,直到备份完结才统一释放锁。5.6则是备份完一个表,就自由多少个锁,达成首借使由此innodb的保存点机制。相关的bug能够参照链接:

参照他事他说加以考察文献

 

TABLE WITH READ LOCK详解,flushlock FLUSH
TABLES WITH READ
LOCK简称(FTWENCOREL),该命令重要用于备份工具得到一致性备份(数据与binlog位点相配)。
由于…

 

以下为本人在工作中的碎碎念,记录的可比散乱……

1.介绍:

………………………………………………………………

MySQL有的时候表,属于session等第,当session退出时,有的时候表被剔除。一时表允许与其余表同名,并单独维护在thd的结构体中;由此,分化的session能够创设同名的不经常表,并且只操作自身有所的一时表;

在mysql里面有三个参数table_cache,当设置过大时,会发生显著的功用下落。那是因为扫描open_cache哈希表时,使用的线性扫描,时间复杂度为O(n),mysql的bug
list上有人提供了三个patch(

 

 

 

第一,大家分析一下mysql在开垦三个表时如何工作:

成立偶尔表的语法比相当粗略:

 

 

在mysql里,table_cache是一个比较首要的参数。由于八线程机制,各类线程独自展开自身须求的标的文件描述符,而不是共享已经张开的。

[email protected]
03:26:44>show create table tmp1\G

 

*************************** 1. row
***************************

 

       Table: tmp1

 

Create Table: CREATE TEMPORARY TABLE `tmp1` (

  1. table_cache key (见create_table_def_key)

  `a` int(11) NOT NULL AUTO_INCREMENT,

在内存里,table cache使用hash表来存款和储蓄,key为 
database_name\0table_name\0+(可选的,用于有时表)

  `b` int(11) DEFAULT NULL,

 

  `c` int(11) DEFAULT NULL,

那边对于一时半刻表会做特殊管理,要求追加额外的新闻来保管有时表在slave端是头一无二的

  PRIMARY KEY (`a`)

日增8个字节:前4个字节为master thread id,后4个字节为slavb

) ENGINE=InnoDB DEFAULT CHARSET=latin1

 

1 row in set (0.00 sec)

 

 

2.展开表时候的管理:open_table

当成立不常表后,会在tmp文件夹下生成多少个文件:

 

#sql3e95_1a_0.frm

 

#sql3e95_1a_0.ibd

***************

 

要求的检讨:线程栈是或不是丰富,thd是或不是被kill

那就是说MySQL本人毕竟是什么创立和删除偶然表的吗?

**************

 

全局锁:lock_open

2.创建

*************************

执行SQL:

第一决断是不是是有时表

 

*************************

CREATE TEMPORARY TABLE `tmp1` (   `a` int(11) NOT NULL
AUTO_INCREMENT,   `b` int(11) DEFAULT NULL,   `c` int(11) DEFAULT
NULL,   PRIMARY KEY (`a`) );

此间有一段很风趣的逻辑,当要求开拓表时,总是先从临时表链表中查找表。约等于说,当存在二个与实际表同名的偶然表时,会一连操作不常表

 

if (!table_list->skip_temporary)

1)断点:ysql_execute_command

  {

 

    for (table= thd->temporary_tables; table ; table=table->next)

mysql_execute_command:

    {

2205      switch (lex->sql_澳门金沙vip,command) {

 

(gdb)

 

2532        if (!(lex->create_info.options &
HA_LEX_CREATE_TMP_TABLE))

**********************************************

(gdb) p lex->create_info.options          ——–if语句里为false

非有时表,且处于pre-locked 或lock_tables mode(thd->locked_tables
|| thd->prelocked_mode)

$2 = 1

即该线程已经开发或锁定了一些表,从thd->open_tables里询问,当不设偶尔,重返error

         
create_table_precheck——检查是或不是有所成立表的权限,以及表名在大局链表上是不是已存在(有的时候表无需检查)

**********************************************

         

if (thd->locked_tables || thd->prelocked_mode)

          append_file_to_dir     ——Fix names if symlinked tables

  {                              // Using table locks

 

    TABLE *best_table= 0;

           if (select_lex->item_list.elements)              
——————-当为create
….select那样的话语时select_lex->item_list.elements为非0值,这里大家只思索轻松的意况

    int best_distance= INT_MIN;

                 if ((result= new select_create))

    for (table=thd->open_tables; table ; table=table->next)

                           res= handle_select(thd, lex, result, 0);

    {

           else

 

               (1)mysql_create_like_table          
—————create table like…类似的说话

 

               (2)mysql_create_table                
—————首要剖判那个函数

 

 

*******************************************************

2)断点:mysql_create_table

健康景况:

 

  1. 第一尝试从table cache中取table

  2. 当找到的TABLE实例是nam-locked的,或许部分线程正在flush
    tables,大家要求等待,直到锁释放

  3. 假设不存在那样的TABLE,大家供给创立TABLE,并将其插足到cache中

mysql_create_table

!这个操作都急需全局锁:LOCK_open,来爱慕table cache和磁盘上的表定义

       mysql_create_table_no_lock

*******************************************************

             check_engine

 

             file = get_new_handler

一经这是该query张开的率先个表:设置thd->version =
refresh_version,那样,当大家展开剩余表的经过中,如若version产生了变动,则须求back
off,关闭全数曾经张开的并再度展开表

3842      set_table_default_charset(thd, create_info, (char*) db);

目前refresh_version只会被FLUSH TABLES命令退换

3844      if (mysql_prepare_create_table(thd, create_info,
alter_info,

 

3854      path_length= build_tmptable_filename(thd, path,
sizeof(path));  
—–创制不常表文件名:#sql{进程id}_{thread_id}_{当前线程的不经常表整数标记thd->tmp_table}               

 if (thd->handler_tables)        

3978      rea_create_table
——————————————————————–创建frm文件和ibd文件

    mysql_ha_flush(thd);  
//刷新(关闭并标识为re-open)全数供给reopen的表

3986     
open_temporary_table————————————————————-展开临时表

 

                            (1)构建table和table_share结构体

 

                           
(2)将table结构体参预到thd->temporary_tables链表中