`
丁林.tb
  • 浏览: 797243 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

InnoDB表快速修改字段名方案

阅读更多

最近被问到一个问题,InnoDB表,只修改一个字段的名字,定义不修改,是否有快速方案。

这个需求的意义来源于,在表设计初期可以预留一些字段,但在预留字段投入使用时,最好能够赋予一个有意义的名字以方便使用。

 

复现

以下实验基于5.1.48版本。

创建一个简单表

 

CREATE TABLE `t` (

  `c1` int(11) DEFAULT NULL,

  `c2` int(11) DEFAULT NULL

) ENGINE=InnoDB DEFAULT CHARSET=gbk;

 

插入10w条数据。将字段c2改名为c3.

 

mysql> alter table t change c2 c3 int(11) default null; 

Query OK, 100000 rows affected (4.29 sec)

Records: 100000  Duplicates: 0  Warnings: 0

 

可以看到,虽然只是简单修改了字段名,在实验机器上耗时达到4.2s,显然重做了所有数据。由于这个表没有索引,数据量也比较小,如果对于更大数据的表,则需要更长的操作时间。

 

分析

我们知道,在

Innodb_file_per_table参数下,每个InnoDB表有两个文件t.frmt.ibd. 实际上,表字段信息只保存于t.frm。这个文件保存了表的定义信息,只有8k 仅修改字段名,实际上不需要重作数据,如果能够只对t.frm做修改,则可以加快上面这个alter语句的执行速度。

 

 

 

源码相关

可以想象MySQL框架中应该是调用了InnoDB引擎的某个函数,用于判断是否需要重做数据。

我们追踪一下alter table语句的执行流程,在mysql_alter_tablesql_table.cc)函数中,我们看到这个局部变量need_copy_table,它有三个可能的取值。 

ALTER_TABLE_METADATA_ONLY= 0,

  ALTER_TABLE_DATA_CHANGED= 1,

  ALTER_TABLE_INDEX_CHANGED= 2

       显然这个取值的判断结果,决定了后面的执行流程。

mysql_alter_table中调用了compare_tables用于判断alter前后的表做了多大的改动,后者在这个语句中修改了need_copy_table的值。

 

  /* Check if changes are compatible with current handler without a copy */

  if (table->file->check_if_incompatible_data(create_info, changes))

  {

    *need_copy_table= ALTER_TABLE_DATA_CHANGED;

    DBUG_RETURN(0);

  }

 

这个check_if_incompatitble_table的函数实现在handler/ha_innodb.cc中。这个函数的返回值可能是COMPATIBLE_DATA_NO表示表改动前后不兼容(需要重做数据)或COMPATIBLE_DATA_YES兼容(不需要重做)。

该函数有如下片段

 

        if (check_column_being_renamed(table, NULL)) {

                return COMPATIBLE_DATA_NO;

        }    

 

其实现逻辑是,如果有任何一个字段名被修改,则返回COMPATIBLE_DATA_NO

 

简单修改

    有了上述分析,要做到快速修改表字段名,只需要把调用check_column_being_renamed的这三行注释掉即可。重新编译发布后,执行结果如下。

 

mysql> alter table t change c2 c3 int(11) default null;      

Query OK, 0 rows affected (0.01 sec)

Records: 0  Duplicates: 0  Warnings: 0

 

可以看到,这回执行基本不需要时间. 对比修改前后的t.ibdMD5,没有修改,而t.frm中只是将c2的字段名改为c3,其他不变。

 

问题!!

这里的问题是,这个修改,是否会有副作用?虽然我们知道修改字段名应该是对数据时没有影响的,但MySQL就是这么实现了。

更深入的调查带来了“坏消息“。 MySQL 5.1.45版本中,就没有这个字段名的判断,也就是说在5.1.45中仅修改字段名是只修改frm文件的。

 

在新版本中特别加入的判断,是否有什么原因?这是撰写本文的意图。若有与此相关的bug或者文章说明,请回复或站内私信我。

 

延伸

       实际上,关于这个问题,还可以继续深入,这里抛砖引玉。

1)      如果上述修改有副作用,副作用是什么,是否可以通过简单修改ibd文件,仍达到快速修改的目的?

2)      在例子中我们简单试验了修改字段名。对于varchar字段,alter table将字段长度增加,是否也可以按照上述思路快速修改?因为我们知道对于还没有数据的varchar字段长度改变,并不影响聚簇索引上的数据。  如果可行,对于预留varchar字段作为扩展来说,也是很有意义[实现请看下篇]。

9
1
分享到:
评论
2 楼 丁林.tb 2011-01-08  
"在发现varchar字符集相关bug后,还由于fast alter的其它的bug,"
这些bug在5.1.48或5.5还存在吗

如何复现呢?
1 楼 victor666666 2011-01-08  
5.1初期是支持的,在发现varchar字符集相关bug后,还由于fast alter的其它的bug,取消了fast alter,只是的copy table。
(我估计是后续的修改没有跟上,oracle mysql开发速度赶不上mysql AB的)

5.5.8版本,我看传入的参数也是null,就是说只要rename column,就全重建

相关推荐

    整理SQL面试工作中常用的语句大全

    创建表时需要注意不要使用关键字作为表名或字段名,如insert、use等。下面是一个简单的示例: CREATE TABLE parent(id INT NOT NULL, PRIMARY KEY (id)) CREATE TABLE child(id INT, parent_id INT, INDEX par_ind ...

    数据库学习笔记.doc

    - **创建表**: `CREATE TABLE`语句定义表结构,包括字段名和数据类型。可设置表选项,如字符集、校对集和存储引擎(如InnoDB、MyISAM)。表可以显式或隐式指定所属数据库。 - **查看表**: `SHOW TABLES`列出所有表...

    mysql基础知识.pdf

    * 配置 MySQL,包括机器类型、是否支持事务功能、innodb 表空间、连接数量、字符集设定等。 * 配置安全选项。 * 启动 MySQL 服务。 MySQL 的使用: * 使用 MySQL 客户端/服务器架构,包括客户端和服务器端程序。 ...

    oracle到mysql的迁移

    解决方案是确保MySQL的数据库名与Oracle的大小写一致,表名和应用程序中的SQL字符串保持一致,对于字段名,如果在应用程序中使用了双引号,应确保SQL中的大小写与双引号内的字符相同。 2. **保留字问题**:Oracle...

    windows下MySQL维护方案

    它能快速计算表行数,且可以与其他字段一起创建联合索引。 总结起来,Windows下的MySQL维护主要包括日志设置、数据备份以及对不同表类型的理解和选择。定期检查和维护日志可以帮助诊断和解决问题,而定期备份则保障...

    mysql处理添加外键时提示error 150 问题的解决方法

    你可能通过修改 cascade 的属性值或者把字段属性设置成 allow null 来搞定这个 bug。 6. 字符集和_collate 不一致 请确定你的 Charset 和 Collate 选项在表级和字段级上的一致。否则,Error 150 将会出现。 7. ...

    数据库的三大范式及五大约束.docx

    设置外键的语法为:CONSTRAINT 外键名 FOREIGN KEY (外键字段)REFERENCES 参照表 (参照字段) ON DELETE SET NULL ON UPDATE CASCADE。 外键约束的参照操作 外键约束的参照操作有四种:RESTRICT、CASCADE、SET NULL...

    mysql数据库方面笔试面试题(带答案)

    - 存储方式:InnoDB表数据和索引存储在同一结构中,通常位于共享表空间或独立表空间。 - 支持事务:是MySQL默认的存储引擎,支持事务处理、行级锁定及外键约束。 - 自动恢复能力:即使系统故障也能保证数据的一致...

    mysql的使用心得

    修改字段名** - **语法** - `ALTER TABLE tb_name CHANGE old_col new_col definition;` - **应用场景** - 当需要更改字段名称或调整其数据类型时非常有用。 **2. 使用临时变量** - **示例** - `SELECT @var...

    mysql学习总结.zip

    它的设计目标是提供快速、稳定和易用的数据库解决方案,适用于各种规模的企业和项目,从小型网站到大型企业应用。 二、MySQL核心概念 1. 数据库(Database):存储数据的容器,可以包含多个表。 2. 表(Table):由...

    mysql.zip_mysql文档

    创建数据库使用`CREATE DATABASE`,创建表则使用`CREATE TABLE`,需定义字段名、数据类型和约束条件。 4. **数据类型**: MySQL支持多种数据类型,如整数(INTEGER)、浮点数(FLOAT、DOUBLE)、字符串(VARCHAR、...

    Mysql基础总结思维导图

    创建表是使用MySQL的第一步,通过CREATE TABLE语句定义表结构,包括字段名、数据类型、是否允许为空等属性。此外,还可以使用ALTER TABLE来修改已有表的结构,如添加、删除或修改字段。DROP TABLE用于删除不再需要的...

    数据库课程设计报告模板

    接下来是逻辑设计,将ER模型转化为具体的表结构,包括字段名、数据类型、主键、外键等。主键是用于唯一标识一条记录的字段,而外键则用于关联不同表。在这个阶段,要确保数据的一致性和完整性,避免冗余和异常。 ...

    实用的mysql下载

    - 表的创建:使用`CREATE TABLE`语句定义表结构,包含字段名、数据类型、约束等。 - 数据插入:`INSERT INTO`命令用于向表中添加数据。 - 查询操作:利用SQL查询语言,如`SELECT`、`WHERE`、`JOIN`等,进行数据...

    mysql管理器.rar

    同时,可以修改现有表的结构,如添加、删除或修改字段,以及进行表的优化和分析。 4. **数据操作**:MySQL管理器支持数据的导入导出,例如从CSV或其他数据库格式导入数据,或将数据导出为多种格式。它还提供了一种...

    mySQL数据库

    - **创建表**:使用`CREATE TABLE`定义表结构,包括字段名、数据类型、主键等。 - **插入数据**:使用`INSERT INTO`语句将数据添加到表中。 - **查询数据**:使用`SELECT`语句进行数据检索,可以配合`WHERE`、`...

    MySQL客户端

    4. 表管理:创建、修改和删除表结构,定义字段类型、约束等。 5. 用户管理:创建、删除和管理数据库用户,设置权限。 6. 备份与恢复:对数据库进行备份,防止数据丢失,并在需要时恢复数据。 7. 日志管理:查看错误...

    MySql5.1参考手册

    创建表时,可以定义字段名、数据类型、主键、索引等属性。 四、SQL语言基础 SQL(Structured Query Language)是操作MySQL数据库的语言。包括数据查询(SELECT)、数据插入(INSERT)、数据更新(UPDATE)、数据...

    MySQL5.5中文版

    7. **更大的元数据限制**:允许更大的表名、字段名和索引长度,以适应更复杂的应用需求。 8. **更好的内存管理**:优化了内存使用,减少了内存碎片,提高了服务器效率。 9. **新的API和接口**:提供了新的C API,...

Global site tag (gtag.js) - Google Analytics