MYSQL的DDL该怎么理解及应用
MYSQL的DDL该怎么理解及应用,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。
DDL 操作一直是我们的 MYSQL 的一个软肋,从MYSQL 5.6 其实相关的alter 语句已经有了改变,也就是题目的的inplace 和 copy 。其实很多人都知道,但用的比较少,因为有pt-OSC 工具呀,还有另外一个工具gh-ost。
维护现在有提起这串豆腐的原因就是MYSQL 8 发展的太快, pt 工具有点跟不上,根据官方的文档,8.013后的版本,PT的部分工具就开始有的时候使用上会出现各种问题。
所以我们在mysql 的正根 alter 语句在高版本上还的拿出来用,而这里面就牵扯,什么时候 inplace 什么时候 copy 到底这都是什么鬼 ?MYSQL 的 DDL 好累心。
OK 下面就是一段官方+测试的东西 + MGR MYSQL 8.018
本次主要是针对字段的DDL 的 增删改来进行的
从上面的8.0 提供的表来看
下面是mysql 5.7 提供的,可以很清晰的看出,的确死不一样了,多了一列叫Instant
但实际上可以看出这个立即能做的事情不多,adding a column ,setting a column default value , Dropping the column default value 这些才可以进行instant 但 最常用到的 adding a column也上面有一个* 号,这说明不可以都可以,是要有条件的。
条件:
1 要不你就添加字段,你要是混合使用alter table语句,那恕不进行instant的操作,例如一条语句又是加字段,又是删字段
2 字段只能加到表最后一列,你要是想在之间加什么字段,恕不管用
3 表的row_format 不能是压缩的 compressed 的格式
4 表里面有全文索引,no no no 不可以
5 临时表不可以
6 数据字典表不可以
添加字段还是蛮快的。下面我们在一个新表,并且一直插入数据的状态下,看看添加字段还这么惬意吗?
我们看看结果如何
DROP TABLE IF EXISTS test.test;
CREATE TABLE test.test(
id int(10) not null auto_increment,
name varchar(20) not null,
age smallint not null,
work_years smallint not null,
PRIMARY key (`id`)
)ENGINE INNODB DEFAULT CHARSET utf8 COMMENT 'test';
#清空数据
TRUNCATE table test.test;
*/
#定义存储过程
delimiter //
DROP PROCEDURE IF EXISTS insert_test_val;
##num_limit 要插入数据的数量,rand_limit 最大随机的数值
CREATE PROCEDURE insert_test_val()
BEGIN
DECLARE i int default 1;
DECLARE a varchar(20) ;
DECLARE b smallint ;
DECLARE c smallint ;
WHILE i<=1000000 do
set b = FLOOR(rand()*50);
set c = FLOOR(rand()*10);
if i mod 2 = 0 then
set a = 'peter';
elseif i mod 3 = 0 then
set a = 'jimmy';
elseif i mod 5 = 0 then
set a = 'Tim';
elseif i mod 4 = 0 then
set a = 'semon';
else
set a = 'lisa';
end if;
if b < 20 then
set b = b + 15;
end if;
INSERT into test.test values (null,a,b,c);
set i = i + 1;
END WHILE;
END
//
#调用存储过程
call insert_test_val();
我们在test 库建立一个表,并且往里面插入大量的数据,然后我们
alter table test add column column1 varchar(500) ,ALGORITHM=INSTANT;
在这个表上添加一个字段,结果如何
SESSION 1
SESSION 2
字段瞬间添加上了,但是存储过程在运行的途中直接报错,通过上表的实验证明 MYSQL 8 添加字段,不在是一个问题,PT 工具可以收手了。
当然这里添加的是一般的column如果你要添加自增的列,则就不可以这样做,还是需要不能进行 DML 操作,类似锁表的操作,好在MYSQL 里面添加自增序列的人不多,大多都是添加普通字段而已。
虽然可以瞬间将阻碍的DML 操作终止,并快速添加字段,但这在生产上来说对应用程序的某些事务性的操作时有害的,所以使用的时候,要小心,避免产生不愿意发生的"特殊情况"。instant 好处是只对数据字典中的元数据进行更改。在SE更改期间不需要获取元数据锁,也不涉及表的数据。这个更改也影响了LOCK=…语义。没有必要为INSTANT algorihtm指定锁。
任何不能立即完成的操作设置ALGORITHM=INSTANT,您将得到一个错误,如下所示。这里的思想是预先失败并快速失败,而不是进行无声的转换并在幕后切换到另一个算法。
所以这是要注意的。这个功能是由腾讯游戏的DBA 团队提出的功能改进。
那这个更改对实际当中的意义在哪里
1 对于大型表,这可能需要很长时间,特别是在复制设置中。
2 磁盘空间需求将增加一倍以上,大致与现有表的大小相同。
3 DDL操作需要大量资源,对CPU、内存和IO的要求很高。这将从用户事务中窃取资源。
4 如果涉及复制,用户可能需要等待更长的时间才能准备好从服务器。DDL完成后将外部化
粗浅的说完alter table 的 instant 的问题, 下面的说说经常要添加索引的问题,在添加索引时是不能使用instant的功能的。目前在MYSQL 8 里面的最优的还是inplace的方。(在你无法使用工具的时候)
我们继续,一个测试,我们往test表里面插入数据,同时在另一个线程添加索引。
session 1
session 2
他大致的操作步骤
新建frm临时文件
锁原表,不许DML,可以查询
按聚集索引顺序,查数据,找索引列数据,排序并插入到新的索引页中
原表不能读操作,也就是原表此时不提供读写服务
进行rename操作,替换frm文件,完成DDL过程
从上边的图可以看到,索引已经添加并且表中国的数据也一直在插入,并没有产生什么看似不良的影响。(以上操作在MGR 集群中操作)
当然这不能说明,就不会有问题,生产系统的复杂性不是我们可以想象的,所以以上测试仅仅代表他能,但对非常繁忙的系统还是要小心。
而算法inplace--顾名思义,它修改表的模式,而不创建原始表的临时表,而是修改原始表本身。在更改表模式(DDL)期间,它不会导致对原始表的读写锁(数据操作语言)
算法copy--顾名思义,它改变了模式的现有表创建一个新的临时表改变模式(在我们的例子中,添加一个新的列),迁移到新的临时表的数据,改变了链接到新表,滴旧表,完成了。
使用ALGORITHM=COPY子句运行的ALTER TABLE操作可以防止并发的DML操作。仍然允许并发查询。也就是说,表复制操作总是至少包含LOCK=SHARED(允许查询,但不允许DML)的并发限制。您可以通过指定LOCK=EXCLUSIVE来进一步限制此类操作的并发性,这可以防止DML和查询。
看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注行业资讯频道,感谢您对的支持。