‘壹’ 如何避免 Mysql 修改表结构时导致表无法使用的问题
来源:oschina.net 作者:whats_java
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
它阐述了即便使用了诸如pt-osc之类的工具,充分了解你想解决的问题是很重要。下面的流程图会帮助你当你了解修改了MYSQL数据库的结构的注意事项。请仔细阅读建议尽管有些图上未标出,例如磁盘空间,IO加载等。
选择合适的DDL操作
确保能清楚了解在修改表结构对你的系统会产生何种影响,并选择合适的方法来使这种影响降到最低。有时这意味着需要将改动延期直到系统到了不常使用的时候或者使用能在操作期间不锁表的工具。当你表中有触发器的时候一般直接修改表结构。
-大多数情况下pt-osc正是我们所需要的
-在很多案例中pt-osc是需要的,但是用法需要稍作调整
-在少数情况下pt-osc不是很合适,我们需要考虑本地阻塞修改,或者采用转移的操作改成在副本集中复制。
‘贰’ 如何给SQL Server数据库设置修改表结构的权限
创建好用户后,几个需要赋权限的地方,写出来以备后用。
1.在安全性用户属性中,登录用户的服务器角色为public
2.
用户映射到数据的数据库角色成员身份为:db_owner和public,默认架构为dbo
3.
状态为允许连接到数据引擎和登录
在允许访问的数据库属性权限中,创建用户权限
1.加上读取、更新、删除,
2.加上控制和连接复制这两个,用户可以在sql
server管理界面中直接连接,
3.加上更改任意架构,用户可以修改表结构
把其他的权限设为拒绝,这样他就只有读取、更新、删除,及修改表结构的权限
‘叁’ SQL的数据表中,第一列的数据为什么修改不了我一修改,它就提示“无法编辑该单元”。
一般是主键约束引起的.如果确实想改,也是可以改的.
alter table 你的数据表
NOCHECK all constraint;--禁用所有约束约束, 禁用后就可以改了
alter table 你的数据表
CHECK all constraint; --启用该表所有约束
‘肆’ SQL Server阻止保存修改表结构的解决方法
在我们的程序开发中,有时候会由于需求的变化而要修改数据库中的表结构。可能是增减列,也可能是修改数据类型,或者修改列名等等。但修改表结构是个危险操作,默认情况下,当你修改表结构时,会弹出如下提示框
上图是修改DeUser表中列的数据类型(从varchar修改为int),然后保存时弹出的提示框。如果我们不想重新创建这张表,只是想在原有的基础上修改它的结构该怎么办呢?
步骤如下:
步骤1.打开SQL
Server
Management
Studio
步骤2.选择Tools
(工具菜单)
步骤3.选择Options
(选项)
步骤4.找到Designers
(设计器)
步骤5.选择Designers下的Table
and
Database
Designers
(表和数据库设计器)
步骤6.去掉右边的勾选项Prevent
saving
changes
that
require
table
re-creation
步骤7.保存
具体细节如下图所示:
建议初学数据库的朋友在使用的时候取消这个选项,方式是在Management
Studio里找菜单栏上的"工具"然后点击下面的选项,在出现的下面的这个界面中展开Designers,选中"表设计器和数据库设计器",把"阻止保存要求重新创建表的更改"前面的勾打掉。
以上就是SQL
Server
阻止保存要求重新创建表的更改问题的设置方法,希望对大家有所帮助,谢谢大家的阅读。
‘伍’ 在SQL Server中,如原表中有数据,修改表结构对数据有何影响
根据修改的内容不同而有不同结果。
如果新增加字段,不会有任何影响,新增加的字段内容为空或者你设置的默认值。
将有数据的字段加长,不会有任何影响。原数据保留。
将有数据的字段删除,会造成该字段数据丢失。
将有数据的字段长度减少,可能会造成该字段数据丢失,也可能不会,跟据实际存储内容的长度决定。
修改原字段的数据类型,不确定的结果,一般不要这样操作。
‘陆’ sql server 2008 为什么修改表的时候总是修改不了,需要设置什么吗
且不说你前边的拼接对不对
最后一个pivot运算用错了,前面不能select
*
对于pivot运算,select后面的内容是由要求的
‘柒’ 怎么解决sqlserver修改被阻止的提示
在修改已经创建的表的时候,经常会弹出如下图所示框框,这是因为您已经启用了 “组织保存要求重新创建表的更改”,取消此项设置即可保存
‘捌’ SQL查询分析器中修改表结构出现下面的问题,在线求助
表中有数据和字段依赖。你可以将该表的建表SQL
重新执行一下。不要用ALTER。这个操作权限级别
一般很低,依赖限制很多。
if exists (select name from sysobjects where type = 'U' and name = '产品表')
drop table 产品表
go
create table 产品表 (
。。。。。。。
, 规格说明 VARCHAR(40) not null default ''
, 。。。。
, primary key (。。。) )
go
‘玖’ 如何解决SqlServer2008修改表结构后无法保存的问题
在使用sql2008时,在修改一张表的结构保存时,提示“您对无法重新创建的标进行了更改或者启用了“阻止保存要求重新创建表的更改”选项。”,试了几次一直是这个错误,删除表后重建,然后还是发生了这个错误。于是寻求谷歌的帮助,发现已经有很多人碰到过这个问题了 原来是当用户在在SQL Server 2008企业管理器中更改表结构时,必须要先删除原来的表,然后重新创建新表,才能完成表的更改,如果强行更改会出现以下提示:不允许保存更改。您所做的更改要求删除并重新创建以下表。您对无法重新创建的标进行了更改或者启用了“阻止保存要求重新创建表的更改”选项。 如果要去掉此提示,打开SQL 2008 在最上面 工具-〉选项-〉左侧有个 Designer->右侧阻止保存要求重新创建表的更改(右侧) 把钩去掉就可以了。网上的文章都说修改完选项后需要重启SqlServer08,不过由于我比较懒,没有重启,结果还是生效了
‘拾’ SQL表结构不能修改,但是我从外部写入的数据字段是不固定的,请问有什么解决办法呢
把字段定义成VCHAR型,它是动态的。如VCHAR(1000),这样如果只放5个字符,那就只占用5个字符的空间,如果你放1000个字符进去,就占用1000个字符的空间。或者使用大字段。你可以把数据类型部分好好看一下就明白了。
补充:也不存在问题,ALTER TABLE啊,这样就不搞定了。这都属于正常操作啊。