MySQL中修改表结构时需要注意的一些地方

MySql 在修改表结构的时候可能会中断产品的正常运行影响用户体验,甚至更坏的结果,丢失数据。不是所有的数据库管理员、程序员、系统管理员都非常了解Mysql能避免这种情况。DBA会经常碰到这种生产中断的情况,当升级脚本修改了应用层和数据库层,或者缺乏经验的管理员、开发在不是很了解Mysql内部工作机制的情况下修改了规范文件。

真相是:

  • 直接修改表结构的过程中会锁表(在5.6版本之前)
  • 在线的数据定义语言在5.6版本不总是在线的而且也会锁表
  • 就算使用Percona工具包(在线修改定义文件)也会有若干个步骤会锁表

Percona MySQL  服务器开发团队鼓励用户在计划或者执行数据库迁移的时候先和我们沟通。我们的目标是基于用户给出的各种情况给出最佳的方案。旨在避免锁表当用户对非常大的表执行DDL,以确保应用能像平常一样正常运行,同时也在努力改善响应时间或增加系统功能。最差的情况是确保那些经不起当机的系统在黄金交易时间正常运行。

我们使用的大多数安装包仍然小于Mysql5.6,这需要我们不停尝试新的安装环境来把数据库迁移造成的损失降到最低。这可能需要一个能“在线修改规范定义文件”的工具来升级或者修改规范文件。Mysql5.6解决这一问题的做法是通过减少重建表和锁表的场景,但这个方法不能覆盖所有的可能的操作,例如当修改一列的数据类型时必然需要全表重构。Przemys?aw和 Malkowski在去年尽可能详尽的讨论了Mysql5.6运行中修改定义。

  • 随着 MySQL 5.7的新功能, 我们寻求不会锁表的DDL操作 例如; 表优化 和 索引重命名. (More info)

对于Mysql5.6的用户,最好的建议是回顾一下数矩阵来熟悉在MYSQL之外执行定义的更改,好消息是我们很擅长解决这一问题。

说实话,锁表操作会经常被忽视,在操作30M大小的表时我们更倾向于直接修改,但是30G,300G的表就要考虑一下了。当使用率不高或者对锁定时间要求不是很高的的系统来说直接操作也许更好。可是,我们常常会遇到一个需要立即执行的SQL,或者因为性能问题需要紧急增加一个索引来减少加载时间。

是否需要在系统在线期修改表定义

上面提到,在线修改表定义是工作流中的一个模块。通常是不错的解决方案,但也会遇到不能使用的场合,例如:当某个表使用了触发器。了解pt-osc在我们项目中的工作过程很重要,让我们来看一下源代码:

代码如下:

[moore@localhost]$ egrep 'Step' pt-online-schema-change
# 步骤 1: 创建一个新表
 
# 步骤 2: 修改清空表. 这应该比较快,
# Step 3: 创建触发器来捕获原始表的改变 <--(锁定元数据)
 
# Step 4: 复制数据.
# Step 5: 重命名表: <--(锁定元数据
 
# Step 6: 更新外键 如果是子表.
 
# Step 7: 删除旧表.

我把上面第三步到第五步高亮出来,这是锁表可能引起系统停机的时间。但步骤六设计外键更新是一个循环的操作,是避免在更新关系的时候隐含地重建表。有很多方法可以确保表的完整性约束,在pt-osc的说明文档中详细说明了,在开始之前预览你的表结构包括约束,并知道怎样把修改表定义所造成的影响降到最低。

最近,我们通知了一个拥有高并发高事务量系统的用户运行pt-osc在大型数据表上。这件事对于他们来说很平常,几小时后我们的客服被告知该客户遇到了最大连接数超过的问题。这个问题是如何产生的呢?当pt-osc运行到步骤五的时候会尝试去锁定数据并重命名原表和隐藏表,然而这不会在开启事务的时候立即执行,因此这条线程会被排在重命名后面。这表现在用户应用上就是系统停机。数据库无法开启新的连接并且所有的线程都被阻塞在重命名命令之后。

    5.5.3版本的说明,当开启一个事务时会锁定它会用到的所有表的数据(不依赖于存储引擎),并在事务提交的时候释放锁。这样做确保了在开启事务期间不能修改表的定义。

长远来看我们可以采用一些新的技术来避免这种情况,例如non-default pt-osc的选项,换言之就是不会删除原表把数据换到新表。这种联合脱离了隐藏表和触发器,我们应该鼓励将重命名操作变得原子化。

校订:2.2版本的percona工具新增了一个变量–tries  和变量–set-vars 共同被部署,解决了各种pt-osc操作可能会锁表的情况。pt-osc (–set-vars)默认会设置如下的会话变量当连接到数据库服务器的时候。

代码如下:

wait_timeout=10000
    innodb_lock_wait_timeout=1
    lock_wait_timeout=60

当使用 –tries 我们可以颗粒化地鉴别操作,尝试次数、在尝试的间隔等待。这种组合可以确保pt-osc在合适的时机杀掉自己的等待会话进程,确保线程堆栈的空闲,并提供给我们循环操作来获取管理因触发器、重命名、修改外键而造成的锁。

代码如下:

–tries swap_tables:5:0.5,drop_triggers:5:0.5

说明文档在这里http://www.percona.com/doc/percona-toolkit/2.2/pt-online-schema-change.html#cmdoption-pt-online-schema-change–tries

它阐述了即便使用了诸如pt-osc之类的工具,充分了解你想解决的问题是很重要。下面的流程图会帮助你当你了解修改了MYSQL数据库的结构的注意事项。请仔细阅读建议尽管有些图上未标出,例如磁盘空间,IO加载等。

选择合适的DDL操作

确保能清楚了解在修改表结构对你的系统会产生何种影响,并选择合适的方法来使这种影响降到最低。有时这意味着需要将改动延期直到系统到了不常使用的时候或者使用能在操作期间不锁表的工具。当你表中有触发器的时候一般直接修改表结构。

  • -大多数情况下pt-osc正是我们所需要的
  • -在很多案例中pt-osc是需要的,但是用法需要稍作调整
  • -在少数情况下pt-osc不是很合适,我们需要考虑本地阻塞修改,或者采用转移的操作改成在副本集中复制。
(0)

相关推荐

  • mysql修改表结构方法实例详解

    本文实例讲述了mysql修改表结构方法.分享给大家供大家参考.具体如下: mysql修改表结构使用ALTER TABLE语句,下面就为您详细介绍mysql修改表结构的语句写法,希望对您学习mysql修改表结构方面能有所帮助. ALTER [IGNORE] TABLE tbl_name alter_spec [, alter_spec ...] alter_specification: ADD [COLUMN] create_definition [FIRST | AFTER column_nam

  • 深入mysql存储过程中表名使用参数传入的详解

    BEGIN declare date_str varchar(8);declare table_prefix varchar(20);set table_prefix='mail_rare_visit_';set date_str = DATE_FORMAT(CURRENT_DATE(),'%Y%m%d');set @table_name = concat(table_prefix, date_str);set @s = concat('CREATE TABLE ', @table_name,

  • MySQL学习笔记5:修改表(alter table)

    我们在创建表的过程中难免会考虑不周,因此后期会修改表修改表需要用到alter table语句 修改表名 复制代码 代码如下: mysql> alter table student rename person; Query OK, 0 rows affected (0.03 sec) 这里的student是原名,person是修改过后的名字 用rename来重命名,也可以使用rename to 修改字段的数据类型 复制代码 代码如下: mysql> alter table person modi

  • MySQL表名不区分大小写的设置方法

    原来Linux下的MySQL默认是区分表名大小写的,通过如下设置,可以让MySQL不区分表名大小写:1.用root登录,修改 /etc/my.cnf:2.在[mysqld]节点下,加入一行: lower_case_table_names=13.重启MySQL即可: 其中 lower_case_table_names=1 参数缺省地在 Windows 中这个选项为 1 ,在 Unix 中为 0,因此在window中不会遇到的问题,一旦一直到linux就会出问题的原因(尤其在mysql对表起名时是无

  • MySQL笔记之修改表的实现方法

    我们在创建表的过程中难免会考虑不周,因此后期会修改表 修改表需要用到alter table语句 修改表名 复制代码 代码如下: mysql> alter table student rename person;Query OK, 0 rows affected (0.03 sec) 这里的student是原名,person是修改过后的名字 用rename来重命名,也可以使用rename to 还有一种方法是rename table old_name to new_name 修改字段的数据类型 复

  • php获取mysql数据库中的所有表名的代码

    复制代码 代码如下: $server = 'localhost'; $user = 'root'; $pass = ''; $dbname = 'dayanmei_com'; $conn = mysql_connect($server,$user,$pass); if(!$conn) die("数据库系统连接失败!"); mysql_select_db($dbname) or die("数据库连接失败!"); $result = mysql_query("

  • 如何将MySQL的两个表名对调

    前言 前段实践遇到个问题,在类似pt-osc场景下,需要将两个表名对调,怎么才能确保万无一失呢? 分析 一些人可能就会想,表名对掉还不简单吗,相互RENAME一下嘛. 但是,我们想要的是同时完成表名对调,如果是先后的对掉,可能会导致有些数据写入失败,那怎么办? 解决 其实也不难,从MySQL手册里就能找到方法,那就是:同时锁定2个表,不允许写入,然后对调表名. 我们通常只锁一个表,那么同时锁两个表应该怎么做呢,可以用下面的方法: LOCK TABLES t1 WRITE, t2 WRITE; A

  • Mysql中返回一个数据库的所有表名,列名数据类型备注

    desc 表名; show columns from 表名; describe 表名; show create table 表名; use information_schema select * from columns where table_name='表名'; 顺便记下: show databases; 也可以这样 use information_schema select table_schema,table_name from tables where table_schema='数据

  • MySQL修改表结构操作命令总结

    表的结构如下: 复制代码 代码如下: mysql> show create table person; | person | CREATE TABLE `person` (   `number` int(11) DEFAULT NULL,   `name` varchar(255) DEFAULT NULL,   `birthday` date DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 | 删除列: 复制代码 代码如下: ALTER TA

  • MySQL中修改表结构时需要注意的一些地方

    MySql 在修改表结构的时候可能会中断产品的正常运行影响用户体验,甚至更坏的结果,丢失数据.不是所有的数据库管理员.程序员.系统管理员都非常了解Mysql能避免这种情况.DBA会经常碰到这种生产中断的情况,当升级脚本修改了应用层和数据库层,或者缺乏经验的管理员.开发在不是很了解Mysql内部工作机制的情况下修改了规范文件. 真相是: 直接修改表结构的过程中会锁表(在5.6版本之前) 在线的数据定义语言在5.6版本不总是在线的而且也会锁表 就算使用Percona工具包(在线修改定义文件)也会有若

  • SQL Server阻止保存修改表结构的解决方法

    在我们的程序开发中,有时候会由于需求的变化而要修改数据库中的表结构.可能是增减列,也可能是修改数据类型,或者修改列名等等.但修改表结构是个危险操作,默认情况下,当你修改表结构时,会弹出如下提示框 上图是修改DeUser表中列的数据类型(从varchar修改为int),然后保存时弹出的提示框.如果我们不想重新创建这张表,只是想在原有的基础上修改它的结构该怎么办呢? 步骤如下: 步骤1.打开SQL Server Management Studio 步骤2.选择Tools (工具菜单) 步骤3.选择O

  • mysql alter table命令修改表结构实例

    mysql实例之使用alter table命令修改表结构 mysql alter table语句可以修改表的基本结构,例如添加字段.删除字段.添加主键.添加索引.修改字段数据类型.对表重命名等等操作,本文章通过两个简单的实例向大家介绍mysql alter table的使用方法  实例一:使用ALTER TABLE命令向表中添加字段.修改字段类型以及设置主键. 首先创建一个表,SQL语句如下: mysql> CREATE TABLE myTable( -> ID SMALLINT ->

  • mysql alter table命令修改表结构实例详解

    mysql alter table语句可以修改表的基本结构,例如添加字段.删除字段.添加主键.添加索引.修改字段数据类型.对表重命名等等操作,本文章通过两个简单的实例向大家介绍mysql alter table的使用方法.  实例一:使用ALTER TABLE命令向表中添加字段.修改字段类型以及设置主键. 首先创建一个表,SQL语句如下: mysql> CREATE TABLE myTable( -> ID SMALLINT -> ); 使用desc命令查看表结构: mysql>

  • MySQL数据库线上修改表结构的方法

    目录 一.MDL元数据锁 1.什么是MDL锁 2.MDL锁的问题 二.如何线上修改MySQL表结构 一.MDL元数据锁 在修改表结构之前,先来看下可能存在的问题. 1.什么是MDL锁 MySQL有一个把锁,叫做MDL元数据锁,当对表修改的时候,会自动给表加上这把锁,也就是不需要自己显式使用. 当对表做增删改查的时候,加的是MDL读锁 当对表结构做变更修改的时候,加的是MDL写锁 读与读之间不互斥,读与写,写与写之间互斥,因此 当有一个线程对表执行增删盖茶的时候,会阻塞掉别的线程对表结构修改的请求

  • 详解mysql 中的锁结构

    Mysql 支持3中锁结构 表级锁,开销小,加锁快,不会出现死锁,锁定的粒度大,冲突概率高,并发度最低 行级锁,开销小,加锁慢,会出现死锁,锁定粒度小,冲突概率最低,并发度最高 页面锁,开销和加锁处于表锁和行锁之间,会出现死锁,锁粒度基于表和行之间,并发一般 InnoDB锁问题 InnoDB与MyISAM的最大不同有两点:一是支持事务(TRANSACTION):二是采用了行级锁.  行级锁和表级锁本来就有许多不同之处,另外,事务的引入也带来了一些新问题. InnoDB的行锁模式及加锁方法 Inn

  • sqlserver 2008手工修改表结构,表不能保存的问题与解决方法

    如果点击"保存文本文件"将会弹出保存文本文件的对话框口, 保存的文本文件中的内容是如下: /*    2010年4月5日0:34:53    用户:    服务器: LONGGEL    数据库: longgel    应用程序: */ ChildCaiClass 保存的对于我来说简直是没用的信息,只是记录了事务的发生时间和一些相关信息,结果这样操作了数据库的结构还是没能修改并保存,而是继续弹出上面的那个窗口,这下我就郁闷了. 点击"取消"却弹出 同样也是没有完成表

  • 浅谈mysql中多表不关联查询的实现方法

    大家在使用MySQL查询时正常是直接一个表的查询,要不然也就是多表的关联查询,使用到了左联结(left join).右联结(right join).内联结(inner join).外联结(outer join).这种都是两个表之间有一定关联,也就是我们常常说的有一个外键对应关系,可以使用到 a.id = b.aId这种语句去写的关系了.这种是大家常常使用的,可是有时候我们会需要去同时查询两个或者是多个表的时候,这些表又是没有互相关联的,比如要查user表和user_history表中的某一些数据

  • Oracle中scott表结构与简单查询实例分析

    本文实例讲述了Oracle中scott表结构与简单查询的方法.分享给大家供大家参考.具体分析如下: 1.scott用户的表的结构 查看表结构 desc 表名;//desc emp; emp表: SQL> desc emp; 名称 是否为空? 类型 ----------------- -------- ------------ EMPNO NOT NULL NUMBER(4) 雇员编号 ENAME VARCHAR2(10) 雇员姓名 JOB VARCHAR2(9) 雇员职位 MGR NUMBER(

随机推荐