分享更有价值
被信任是一种快乐

什么是pt-online-schema-change

文章页正文上

什么是pt-online-schema-change,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。首先要说明pt-online-schema-change工具并不是说修改表结构的时候不上锁,通常我们说的锁一般包含innodb 行锁和MDL lock。而pt-online-schema-change工具就是将某些使用COPY算法的DDL操作使用DML操作来代替,换句话说就是使用Innodb row锁来代替MDL lock,因为MySQL原生的COPY算法的DDL会在MDL lock SNW这个类型保护下完整个表复制操作,整个复制过程中是不允许DML操作,因此造成了我们COPY算法的DDL堵塞线程正常的现象,当然哪些DDL可以online进行可以参考官方文档online ddl一节。整个pt-online-schema-change工具修改过程中,只会在rename阶段才会上MDL LOCK的X锁,但是rename操作一般非常快速。我们大概看一下pt-online-schema-change的工作方式,这个实际上开启genrnal log就能看出来下面是重点步骤(我的表名叫做testpt_osc):首先定义出新表CREATE TABLE
test._testpt_osc_new (
id int(11) NOT NULL,
name varchar(20) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
ALTER TABLE
test._testpt_osc_new add index name_index(name)定义三个触发器delete 触发器:
CREATE TRIGGER
pt_osc_test_testpt_osc_del
AFTER DELETE ON
test.testpt_osc
FOR EACH ROW
DELETE IGNORE FROM
test._testpt_osc_new
WHERE
test._testpt_osc_new.id OLD.idupdate 触发器:
CREATE TRIGGER
pt_osc_test_testpt_osc_upd
AFTER UPDATE ON
test.testpt_osc
FOR EACH ROW
BEGIN
DELETE IGNORE FROM
test._testpt_osc_new
WHERE !(OLD.id NEW.id)
AND
test._testpt_osc_new.id OLD.id;
REPLACE INTO
test._testpt_osc_new (id,
name) VALUES
(NEW.id, NEW.name);
ENDinsert 触发器:
CREATE TRIGGER
pt_osc_test_testpt_osc_ins
AFTER INSERT ON
test.testpt_osc
FOR EACH ROW
REPLACE INTO
test._testpt_osc_new (id,
name) VALUES
(NEW.id, NEW.name)使用分块(chunk)拷贝的方式首先需要插入数据的确认上界:
SELECT /!40001 SQL_NO_CACHE /
id FROM
test.testpt_osc FORCE INDEX(PRIMARY)
WHERE ((id >= ‘1’)) ORDERBY
id LIMIT 1999, 2 /next chunk boundary/然后插入:
INSERT LOW_PRIORITY IGNORE INTO
test._testpt_osc_new (id,
name)
SELECT
id,
name FROM
test.testpt_osc FORCE INDEX(PRIMARY)
WHERE ((id >= ‘1’)) AND ((id
最终进行表的重新命名使用RENAME TABLE
test.tp1 TO
test._tp1_old,
test._tp1_new TO
test.tp1
进程重新命名。从整个过程来讲需要注意的几个地方:对于delete和update触发器来讲,delete数据均使用了IGNORE进行修饰,因此即便数据还没有拷贝到新表也不会引发错误。对于update和insert触发器来讲,均使用了replace这种操作来进行,因此如果数据还没有拷贝到新表那么将插入到新表中,如果数据已经拷贝到新表那么将会修改其中的值。因此新表中总是保留的最新的数据。对于分块拷贝数据而言,使用是insert ignore 新表 select 老表 LOCK S 的方式,因此对于触发器插入的最新值,是不会进行修改的也不会报错。打个比方chunk为200 当前拷贝数据到了1000行,但是我们手动修改了第2000行的数据,那么第2000行将会在update触发器的作用下提前插入到新表中,当拷贝数据来到这一行的时候因为使用了ignore则不会重复行的错误,并且数据是最新的。其次每次insert select操作是一个单独的事务。insert ignore 新表 select 老表 LOCK S 的方式 操作存在对新表中加自增锁的可能,这取决于你的参数设置。对于触发器而言,原始语句和触发语句被包裹在一个事务里面,也就是说对于任何一个DML语句而言,修改老表和新表的数据需要的行锁将会在一个事务中存在。pt-online-schema-change 生成的binlog和redo都会比online DDL大得多,效率上讲应该低于online DDL。由于replace操免费主机域名作的存在,因此pt-online-schema-change将会依赖主键或者唯一键,否则将不能工作。我们可以看到整个过程中有如下的重点知识点:触发器和事务Insert ignore/replace语法自增死锁的发生其次对于第4和第5点来讲,有出现死锁的可能。下面我们分别讨论。在pt-online-schema-change中,触发器占据了重要的地位,我们需要了解一下触发器和事务之间的关系。我们常用的触发器包含了before和after触发器,代表着对原表进行DML操作前或者后进行其它的操作,下面是我定义的两个测试的触发器如下:显然如果对t1表进行数据插入,那么会在之前向t2表插入一条数据,然后在之后向t3插入一条数据,这一点可以通过函数调用trace进行验证如下:这里就能够看到顺序了,其次我们还需要知道这些所有的操作会包裹在一个事务里面,这一点也可以通过函数调用trace进行验证,还可以使用binlog进行验证,下面是一次调用的binlog信息:这里我们使用binlog不仅验证了执行顺序并且还验证了所有操作都包含在一个事务里面。既然所有的语句都包裹在一个事务里面,那么加锁的范围就更大了,这不仅关系到本身的DML操作表,并且还关系到触发语句的相关表,需要额外注意。其次所有语句不仅包裹在一个事务里面,并且共享一个错误返回接口,那么如下的错误:我们惊讶的发现t1表一条数据都没有,但是居然返回重复的行。原因就在于虽然t1表没有数据,但是t2或者t3表有违反唯一性检查的可能,因此返回了错误,错误由统一的接口返回给客户端。最后触发器会导致处理逻辑混乱,尽量避免使用触发器。关于ignore语法我们以insert ignore语法为例,一般来讲如果遇到重复行insert ignore语法会通过忽略重复值错误的方式进行跳过,这实际上和replace的处理方式一致,但是replace不同的是如果遇到重复行不是进行忽略,而是执行的delete然后执行insert操作。换句话说他们的触发形式一致,但是触发后执行的行为是不同的,下面我们就来看看。首先对于insert语句来讲我们需要定位到需要插入的位置,这部分略过。这一步对于主键/唯一索引 而言需要判断是否已经有重复的行。其判断标准基本都是通过插入的值进行索引定位,然后判断定位游标的值是否和需要插入值相同,下面是栈帧:主键:二级索引唯一键如果存在重复的行,这需要进行判断了:如果重复的行正在被其他事务持有,那么需要进行进行隐试锁转换,主键的转换操作如下:因为我们知道通常insert锁并不会建立显示的锁。对于如果出现了重复的行,持有重复行数据的事务并没有提交或者回滚,需要其事务完成提交或者回滚,然后再进行相应的抛错或者继续插入。需要注意的是对于replace/insert on dup 在进行唯一性检查的时候,通常加的LOCK_S锁,而其他操作通常加的是 LOCK_X。如果重复的行没有其他事务持有,那么抛出重复行错误,但是注意这里的错误不是返回给客户端的错误,是内部错误HA_ERR_FOUND_DUPP_KEY,这个错误在Innodb层叫做DB_DUPLICATE_KEY(convert_error_code_to_mysql)。如何处理这个错误就和相应的语法有关了。当然如果没有重复的行,那么接下来就可以继续进行insert插入操作了,Insert ignore/replace实现都是进行insert操作。如果有重复行呢?那么接下来进行分析。这里我们也很明白了,对于免费主机域名了insert ignore/replace是通过主键/唯一键进行判断是否重复行的,具体点来说就是如何处理错误HA_ERR_FOUND_DUPP_KEY。
如果表中一个能够判断唯一性的索引都没有,那么即便2条数据一模一样也不会标记为重复行,视为2条不同的数据,当然insert on dup 这里也是同样的逻辑。
在进行唯一性检测的时候,会先检查主键的唯一性,然后依次检查各个唯一索引的唯一性是否满足。首先对于多行插入和insert select来讲,每次innodb层插入的行数为1行,我们应该牢牢树立以行为单位的处理流程,我们可以在函数Sql_cmd_insert::mysql_insert 中找到 一个大的while 循环,这就是处理的循环。我们也需要明白,进行判断唯一性的时候是先判断主键的唯一性,如果满足则插入主键数据,然后依次判断二级唯一索引,如果满足则进行插入。这里涉及到一个问题,如果主键数据插入了,但是二级唯一索引由于违法唯一性那么,前面主键插入的数据是需要回滚的。再或者我们执行的insert select操作,其中前面的一些行不违反唯一性插入了,但是随后的某行违法了唯一性,那么前面插入的数据也是需要回滚的。函数row_insert_for_mysql_using_ins_graph 中进行这种逻辑处理。回滚栈帧:3、对重复错误HA_ERR_FOUND_DUPP_KEY 的处理操作如果有重复的行并且产生了错误HA_ERR_FOUND_DUPP_KEY ,那么就不能进行insert 操作了,这里就会根据不同的语法进行不同的操作了。我们在函数(write_record )中可以找到这种分支处理逻辑。实际上在处理重复行错误的时候,在内部分为了3种方式如下:DUP_ERROR:这个代表的就是普通的insert/insert ignore语句
这是我们普通的操作,如果是insert操作则进行抛错给客户端,如果是insert ignore操作则不进行报错,仅仅做一个警告,如下:
“`
/
If IGNORE option is used, handler errors will be downgraded
to warnings and don’t have to stop the iteration.
/
mysql> insert ignore into tpk2 values(5,’g’,’m’);
Query OK, 0 rows affected, 1 warning (6 min 3.60 sec)mysql> show warnings
-> ;
+————-+———+———————————————————-+
| Level | Code | Message |
+————-+———+———————————————————-+
| Warning | 1062 | Duplicate entry ‘5’ for key ‘PRIMARY’ |
+————-+———+———————————————————-+
1 row in set (0.00 sec)if (last_uniq_key(table,key_nr) &&//是否是检测的最后一个唯一索引
!table->file->referenced_by_foreign_key() &&
(!table->triggers || !table->triggers->has_delete_triggers()))
{
if ((error=table->file->ha_update_row(table->record[1],
table->record[0])) && //调用了是update接口
error != HA_ERR_RECORD_IS_THE_SAME)
if (error != HA_ERR_RECORD_IS_THE_SAME)
info->stats.deleted++; //影响行数+1
goto after_trg_n_copied_inc;
}
else
{

if ((error=table->file->ha_delete_row(table->record[1])))//删除接口 delete
goto err;
info->stats.deleted++; //影响行数+1

/ Let us attempt do write_row() once more ///这里会进行一次循环进行普通的insert操作
}…mysql> replace testpri2(id,a,b) values(7,’b’,’k’);
Query OK, 2 rows affected (2.74 sec)mysql> insert into testpri2(a,b) values(‘mmmmnb’,’ffhhh’) on DUPLICATE KEY UPDATE b=’bj’;
Query OK, 2 rows affected (3.81 sec)关于什么是pt-online-schema-change问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注云技术行业资讯频道了解更多相关知识。

相关推荐: flashback闪回技术的分析

这篇文章将为大家详细讲解有关flashback闪回技术的分析,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。 ##开启flasbbackSQL> alter system set db_recovery_f…

文章页内容下
赞(0) 打赏
版权声明:本站采用知识共享、学习交流,不允许用于商业用途;文章由发布者自行承担一切责任,与本站无关。
文章页正文下
文章页评论上

云服务器、web空间可免费试用

宝塔面板主机、支持php,mysql等,SSL部署;安全高速企业专供99.999%稳定,另有高防主机、不限制内容等类型,具体可咨询QQ:360163164,Tel同微信:18905205712

主机选购导航云服务器试用

登录

找回密码

注册