最近做drop table操作,24G的sas机器,ibd文件17G,大约需要14S,在此期间mysql(5.1.48)基本hang住。详细了解了一下mysql drop table过程,发现是mysql drop table的逻辑引起,主要有2方面的原因:drop table过程会持有buffer pool mutex,做2次遍历--对于大内存的mysql服务器,会导致mysql hang住;rm ibd文件的过程,会持有LOCK_open mutex,对于大表,也会导致mysql hang住。对于第二个问题,bug#41158提到一个解决办法:对磁盘做碎片整理;drop前对ibd文件做一个硬链接,这样drop的时候,ibd文件就不会被rm掉,LOCK_OPEN持有的时间就会很短,drop完之后再单独rm。
下面详细理一下drop table的过程:
drop table的调用路径如下(5.1.58): do_command(sql_parse.cc) ->dispatch_command(sql_parse.cc) ->mysql_parse(sql_parse.cc) ->mysql_execute_command(sql_parse.cc) ->mysql_rm_table(sql_table.cc) ->mysql_rm_table_part2(sql_table.cc:2072)(LOCK_open发生在这里) ->ha_delete_table(handler.cc) ->handler::ha_delete_table(handler.cc) ->ha_innodb::delete_table(handler/ha_innodb.cc)(这里开始就是innodb层的实现) ->row_drop_table_for_mysql(row/row0mysql.c) ->fil_delete_tablespace(fil/fil0fil.c) ->buf_LRU_invalidate_tablespace(buf/buf0lru.c) ->buf_LRU_drop_page_hash_for_tablespace(buf/buf0lru.c)(尝试批量删除被drop的space id的hash index entries,这里开始了对buffer pool的遍历) ->os_file_delete(os/os0file.c)(unlink()发生在这里)
unlink是在innodb的os_file_delete函数内调用的,而mysql_rm_table_part2(sql_table.cc:1923)开始持有LOCK_open,直到调用innodb层drop table完成 & mysql层表定义文件(frm和这个表上的trigger)被删除后才释放,这个就是本文一开头说的drop 大表时引起mysql hang住。
接下来看一下2次遍历的问题。fil_delete_tablespace()在unlink ibd文件前清理buffer pool中对应表的block,具体函数是buf_LRU_invalidate_tablespace()。这个函数一开始就调用buf_LRU_drop_page_hash_for_tablespace(),尝试清理哈希索引中的entries(不保证完全清理),这里开始了对buffer pool的第一次遍历(从后往前),遍历的开始就执行buf_pool_mutex_enter(),拿到buf_pool_mutex。处理完hash index之后,buf_LRU_invalidate_tablespace()就开始了对buffer pool的第二次遍历(从后往前),同样的在遍历的整个过程中持有buf_pool_mutex。如果你的buffer pool比较大,2次 buffer pool的遍历自然会花费很久,mysql也会hang的更久。
mysql5.5引入metadata lock,unlimit的时候持有LOCK_open的问题得到解决。同时对2次遍历的问题做了一些改进:每扫描1024个pages后(满足某些条件,bug#64284),会释放buffer pool mutex;将对lru list的第一遍扫描改为对flush list的扫描。
percona也对这个问题做了一些改进。percona引入buf_LRU_mark_space_was_deleted函数来解决这个问题。扫描lru list,对lru list中要被删除的page做个flag;对AHI加一把共享锁,扫描buffer pool,清理要被删除的page;释放AHI上的共享锁。
其实drop table的这个问题完全是设计产生的问题,按照正常的处理逻辑,drop table 完全不需要处理buffer pool,buffer pool中要被删除的block完全可以通过LRU淘汰掉。这个改动会涉及到比较多的地方,看起来mysql还没有这么做的打算。
另外没有外键的情况下,mysql中的truncate是通过drop table + create table 的方式完成的(mysql_truncate->mysql_truncate_by_delete->mysql_delete->ha_delete_all_rows,sql_delete.cc->ha_innodb::ha_delete_all_rows,handler/ha_innodb.cc->row_truncate_table_for_mysql,row/row0mysql.c->fil_discard_tablespace,fil/fil0fil.c->fil_delete_tablespace,fil/fil0fil.c->os_file_delete,os/os0file.c),因此truncate table也会有drop table所带来的问题,所以drop和truncate大表最好都通过硬链接的方式进行。
参考链接:
http://www.mysqlperformanceblog.com/2011/02/03/performance-problem-with-innodb-and-drop-table/
http://bugs.mysql.com/bug.php?id=56332
http://bugs.mysql.com/bug.php?id=51325
http://bugs.mysql.com/bug.php?id=39939
http://bugs.mysql.com/bug.php?id=41158(LOCK_OPEN is hold while unlink())
http://bugs.mysql.com/bug.php?id=56655
http://bugs.mysql.com/bug.php?id=56696(truncate相关)
相关推荐
MySQL 异常恢复-drop 表恢复 MySQL 异常恢复是指在 MySQL 数据库出现异常情况时,恢复数据库的操作。drop 表恢复是指在 MySQL 数据库中删除表后,恢复被删除的表的操作。undrop-for-innodb 是一种恢复被删除的表的...
本文将深入解析MySQL 5.7.26及8.0版本中`DROP TABLE`的具体实现过程。 首先,我们从标题"drop table - by 姜少华1"可以看出,这是一篇关于MySQL中删除表操作的文章,由姜少华1撰写。接下来,让我们详细探讨这个过程...
MySQL的: drop table if exists 表名; SQL Server的: IF EXISTS (SELECT name FROM sysobjects WHERE name = '表名' AND type = 'U') DROP TABLE 表名; Oracle的: create or replace table 表名 ...; -- 直接写...
MySQL Alter Table 修改表信息 MySQL Alter Table 语句是一种 poderosa 语句,允许用户修改表信息,包括增加或删减字段、更改字段的数据类型和属性、创建或取消索引、修改表的评注和表的类型等。 增加字段 ALTER ...
### MySQL 创建存储过程详解 #### 一、存储程序概述 **存储程序**是可以在MySQL服务器中定义并存储的一组SQL语句。它们的功能类似于过程化的编程语言中的函数或过程,可以封装复杂的逻辑,并且能够在数据库层面...
当我们尝试`DROP TABLE tmp`时,MySQL会根据当前会话的上下文决定删除哪个表。在上述示例中,我们首先创建了一个临时表,然后执行了两次`DROP TABLE tmp`。第一次操作删除了临时表,因为它在当前会话中可见。第二次...
以下是对MySQL、Oracle和SQL Server中`DROP TABLE`用法的详细解释: 1. **MySQL**: 在MySQL中,如果你想删除一个表,并且希望在表不存在时避免出现错误,可以使用`DROP TABLE IF EXISTS`语句。例如: ```sql ...
MySQL提供了一些工具来管理和调试存储过程,例如`SHOW CREATE PROCEDURE`命令可以查看存储过程的创建语句,`DROP PROCEDURE`用来删除不再需要的存储过程,`ALTER PROCEDURE`则用于修改已存在的存储过程。 在压缩包...
综上所述,"Mysql-Table-Difference-SQL-master.zip" 是一个强大的数据库升级辅助工具,它通过自动化对比和脚本生成,帮助我们在数据库管理中省去了大量手动操作,提高了工作效率,是数据库开发和维护过程中不可或缺...
MySQL在进行alter table等DDL操作时,有时会出现Waiting for table metadata lock的等待场景。而且,一旦alter table TableA的操作停滞在Waiting for table metadata lock的状态,后续对TableA的任何操作(包括读)...
可以使用`ALTER PROCEDURE`来更新存储过程的定义,而`DROP PROCEDURE`用于删除不再需要的存储过程。 9. **返回值** 存储过程可以通过`RETURN`语句返回一个整数值,也可以通过OUT参数传递结果。 10. **游标与循环...
5. 数据库管理:在MySQL客户端,可以使用`CREATE DATABASE`、`USE`、`DROP DATABASE`等命令创建、切换和删除数据库。 二、MySQL存储过程 存储过程是预编译的SQL语句集合,可在需要时重复调用,提高效率并简化复杂...
首先,使用 `DROP TABLE` 删除原始表,然后使用 `CREATE TABLE` 语句创建一个同名的新表。这个新表可以是与原表相同的结构,也可以是修改后的结构。示例如下: ```sql DROP TABLE 表名; CREATE TABLE 表名 LIKE 原...
- **命令**: `mysql> ALTER TABLE oauth_clients DROP COLUMN column_to_drop;` - **说明**: 从表 `oauth_clients` 中删除名为 `column_to_drop` 的列。 - **2.4.4 重命名表** - **命令**: `mysql> RENAME TABLE...
drop table if exists departments; drop table if exists employees; drop table if exists jobs; drop table if exists locations; drop table if exists countries; drop table if exists regions; drop table if...
MySQL数据库考试试题及答案 在本文中,我们将对 MySQL 数据库考试试题及答案进行详细的解析,并总结出相关的知识点。 1.数据库聚合函数 ...在 MySQL 中,还有很多其他的知识点,例如索引、视图、存储过程等。
mysql> DROP TABLE yg; ``` #### 创建表 (CREATE TABLE) 使用`CREATE TABLE`语句来创建新的表。 ``` mysql> CREATE TABLE yg; ``` #### 显示所有数据库 (SHOW DATABASES) 使用`SHOW DATABASES`语句来显示所有可用...
MySQL的ALTER TABLE命令是用于修改现有表结构的关键命令,它允许你进行一系列操作,包括添加、删除或修改列,设置或删除索引,更改表名,以及调整其他表选项。以下是对这个命令的详细说明: 1. **添加列**: - ...