mysql 怎么给一个表一次增加多个字段
发布时间:2025-05-20 21:59:42 发布人:远客网络
一、mysql 怎么给一个表一次增加多个字段
1、mysql给一个表一次增加多个字段的代码如下:
2、alter table admin_pay_type add erp_code varchar(20) not null,
3、MySQL是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,目前属于Oracle旗下产品。MySQL是最流行的关系型数据库管理系统之一,在 WEB应用方面,MySQL是最好的RDBMS应用软件。
4、MySQL是一种关系数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。
5、MySQL所使用的 SQL语言是用于访问数据库的最常用标准化语言。MySQL软件采用了双授权政策,分为社区版和商业版,由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,一般中小型网站的开发都选择 MySQL作为网站数据库。
6、由于其社区版的性能卓越,搭配PHP和Apache可组成良好的开发环境。
7、参考资料:mysql怎么给一个表一次增加多个字段--CSDN
二、mysql 如何给大表添加字段
1.能不加字段就不要加,能不修改字段就不要修改,能不删除字段就不要删除,等等为什么要删除字段呢?如果没事,不要蛋疼的找事。实际上,我们那次更新失败后,我们并没有增加那个字段,然后我们一直运行到今天,但是后来还是增加了其他字段
2.增加字段的情况下,如果可以通过增加一个新的表来增加这个字段,那么就增加一个新的表,通过cache或程序来实现join的效果
3.如果能停机,并且停机的时间在你容忍范围之内,数据备份之后停机来做。如果是主从备份,做这样大的操作的时候,停掉主从备份,万一你挂了,备份数据库可以救你。等到一切安全了,重启主从备份;
4.如果上面都不行,这个字段还是要改,要加,需要用到下面的方法,也是扇贝网正在使用的方法;
1.被修改的表 Table A需要有一个记录时间戳的字段,这个时间戳就是每次数据更新,都会更新的字段,这个字段需要有索引,在django里可以使用 auto_now=True
2.创建一个新的临时表 Table B,不是tmp_table,是一个新的表,但是是临时使用的。这个表和要修改的表拥有一模一样的数据结构,加上你要修改的部分,比如增加的字段;
5.把Table A的数据全部复制到Table B,是不是执行 INSERT INTO B(field1, field2) SELECT field1, field2 FROM A?当然不是,这么做不还是锁死了Table A么,这里的迁移就是一个需要细分的地方,需要写一个脚本,让程序每次读取比如5000条数据出来,插入到Table B里面,因为Table B是没有索引的,所以要当心不要使用多进程来做;如果是多进程,要确保插入到B的时候是不会有重复数据的;如果是1000万的数据,每次5000条,假设这个操作需要500ms,那么 2000*200ms= 16分钟。这只是一个估值,具体情况和服务器当时的情况有关,不好细说。另外,我们要记录这个迁移开始的时间点,记为t1;
6.那么这个时候Table A的数据是不是都进入了Table B呢,应当说差不多大部分都进入了,但5中说,这大概需要16分钟,这么长的时间里,可能有新的数据进入了,也有可能已有的数据发生了更新,所以我们要把Table A中在t1之后发生变化的数据查找出来,然后更新到Table B中,我们的做法是:
DELETE FROM B WHERE updated_time> t1;
INSERT INTO B(field1, field2) SELECT field1, field2 FROM A WHERE updated_time>t1;
7.现在A和 B差不多该同步了吧?差不多了,但是6执行完之后, A仍然在写,子子孙孙无穷尽也...,但这个时候 A和 B的差异已经非常非常小了,所以在下一步,我们在一个transaction里执行下面的操作:
DELETE FROM B WHERE updated_time> t2;
INSERT INTO B(field1, field2) SELECT field1, field2 FROM A WHERE updated_time>t2;
PS:如果A表没有时间戳,实际上没有先见之明的人大概不会想到要预留一个时间戳的字段,那么几乎是没有办法快速比较两个表的差异的,这个时候我选择的做法就是放弃修改的数据,只管新的数据了,所以只要把t1, t2换成id就可以了,这样delete语句也省略了,因为没啥好delete的;
千万不要想着根据ID来JOIN然后更新B表的字段来补齐新的数据,如果能把两个千万级别的表JOIN起来,内存有多大呢?
9.上面的解决方案是我们第二次尝试之后犯下了一个巨大的错误,这个错误导致网站瘫痪了大概20分钟,如果你和我一样没有发现问题,那么这就是悲剧的地方。问题就在于我是根据上面的PS来操作的,然后B就华丽地变成了A. B表至今身上是没有索引的,立即悲剧。所以应当在第5步之后按照A的索引为B建立索引,待索引全部好了之后,再继续6。如果不是走PS这条路,而是有时间戳的字段的话,在6的时候会发现这个问题,因为那条Delete慢的超出想像,会明白这里是有问题的
10.新手,请在本地练习之后,再实际操作;可以多操作几次,写一个脚本,服务器上直接执行脚本.
三、MySQL 数据库如何添加列
1、我们先回顾一下,在没有"立刻加列"功能时,加列操作是怎么完成的。我们也借此来熟悉一下本期的图例:
2、当进行加列操作时,所有的数据行都必须要增加一段数据(图中的列 4数据)
3、如上一期图解所讲,当改变数据行的长度,就需要重建表空间(图中灰蓝的部分为发生变更的部分)
4、以上操作的问题在于每次加列操作都需要重建表空间,这就需要大量 IO以及大量的时间
5、"立刻加列"时,只会变更数据字典中的内容,包括:
6、"立刻加列"后,当要读取表中的数据时:
7、由于"立刻加列"没有变更行数据,读取的行数据只有 3列
8、MySQL会将新增的第 4列的默认值,追加到读取的数据后
9、以上过程描述了如何读取在"立刻加列"之前写入的数据,其实质是:在读取数据的过程中,"伪造"了一个新列出来
10、那么如何读取在"立刻加列"之后写入的数据呢?过程如下图:
11、通过判断数据行的头信息中的instant标志位,可以知道该行的格式是"新格式":该行头信息后有一个新字段"列数"
12、通过读取数据行的"列数"字段,可以知道该行数据中多少列有"真实"的数据,从而按列数读取数据
13、通过上图可以看到:读取在"立刻加列"前/后写入的数据是不同的流程
14、通过以上的讨论,我们可以总结"立刻加列"之所以高效的原因是:
15、在执行"立刻加列"时,不变更数据行的结构
16、读取"旧"数据时,"伪造"新增的列,使结果正确
17、写入"新"数据时,使用了新的数据格式(增加了instant标志位和"列数"字段),以区分新旧数据
18、读取"新"数据时,可以如实读取数据
19、那么我们是否能一直"伪造"下去?"伪造"何时会被拆穿?
20、我们推测一下"删除列 B"的最小代价:需要修改数据行中的instant标志位或"列数"字段,这至少会影响到"立刻加列"之后写入的数据行,成本类似于重建数据
21、从以上推测可知:当出现与"立刻加列"操作不兼容的 DDL操作时,数据表需要进行重建,如下图所示:
22、扩展思考题:是否能设计其他的数据格式,取代instant标志位和"列数"字段,使得加列/删列操作都能"立刻完成"?(提示:考虑加列-删列-再加列的情况)
23、在了解原理之后,我们来看看"立刻加列"的使用限制,就很容易能理解其中的前两项:
24、"立刻加列"的加列位置只能在表的最后,而不能加在其他列之间
25、在元数据中,只记录了数据行应有多少列,而没有记录这些列应出现的位置。所以无法实现指定列的位置
26、加列不能涉及聚簇索引的变更,否则就变成了"重建"操作,不是"立刻"完成了
27、按照 WL的说法:"COMPRESSED is no need to supported"(没必要支持不怎么用的格式)
28、"立刻加列"之所以高效的原因是:
29、在执行"立刻加列"时,不变更数据行的结构
30、读取"旧"数据时,"伪造"新增的列,使结果正确
31、写入"新"数据时,使用了新的数据格式(增加了instant标志位和"列数"字段),以区分新旧数据
32、读取"新"数据时,可以如实读取数据
33、"立刻加列"的"伪造"手法,不能一直维持下去。当发生与"立刻加列"操作不兼容的 DDL时,表数据就会发生重建
34、所谓"立刻加列"是否完全不影响业务,是否是真正的"立刻"完成?
35、可以看到:就算是"立刻加列",也需要变更数据字典,那么该上的锁还是逃不掉的。也就是说这里的"立刻"指的是"不变更数据行的结构",而并非指"零成本地完成任务"