• pt-online-schema-change原理分析


    使用pt-online-schema-change工具修改schema时,会先创建一个与原数据表拥有相同结构的新表,然后将原表中的数据逐步复制到新表。

    例如一个拥有id,name数据列的zs表,向该表添加名为uid新列时,使用如下命令:

    root@localhost:mysql3316.sock  14:24:33 [test]>show create table zsG
    *************************** 1. row ***************************
           Table: zs
    Create Table: CREATE TABLE `zs` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `name` varchar(255) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
    1 row in set (0.00 sec)
    
    root@localhost:mysql3316.sock  14:27:10 [test]>SELECT * FROM zs;
    +----+-----------+
    | id | name      |
    +----+-----------+
    |  1 | zhangshuo |
    +----+-----------+
    1 row in set (0.00 sec)
    [root@bogon data]# pt-online-schema-change --alter "add uid int" D=test,t=zs --no-drop-old-table --no-drop-new-table --chunk-size=500 --chunk-size-limit=600 --defaults-file=/usr/local/mysql/my3316.cnf --host=localhost --port=3316 --charset=utf8 --user=root --ask-pass --progress=time,30 --max-load="threads_running=100" --critical-load="threads_running=1000" --chunk-index=PRIMARY --execute

    1.pt-online-schema-change处理上述命令时,会 先根据原zs数据表的结构创建新表,(_zs_new),并将要添加的列加到新表:

    58 Query     SHOW VARIABLES LIKE 'wsrep_on'
                       58 Query     /*!40101 SET @OLD_SQL_MODE := @@SQL_MODE, @@SQL_MODE := '', @OLD_QUOTE := @@SQL_QUOTE_SHOW_CREATE, @@SQL_QUOTE_SHOW_CREATE := 1 */
                       58 Query     USE `test`
                       58 Query     SHOW CREATE TABLE `test`.`zs`
                       58 Query     /*!40101 SET @@SQL_MODE := @OLD_SQL_MODE, @@SQL_QUOTE_SHOW_CREATE := @OLD_QUOTE */
                       58 Query     CREATE TABLE `test`.`_zs_new` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `name` varchar(255) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
                       58 Query     ALTER TABLE `test`.`_zs_new` add uid int
                       58 Query     /*!40101 SET @OLD_SQL_MODE := @@SQL_MODE, @@SQL_MODE := '', @OLD_QUOTE := @@SQL_QUOTE_SHOW_CREATE, @@SQL_QUOTE_SHOW_CREATE := 1 */
                       58 Query     USE `test`
                       58 Query     SHOW CREATE TABLE `test`.`_zs_new`
                       58 Query     /*!40101 SET @@SQL_MODE := @OLD_SQL_MODE, @@SQL_QUOTE_SHOW_CREATE := @OLD_QUOTE */

    2.然后创建after触发器,使原数据表(zs)的insert、update、delete操作内容能传递到_zs_new数据表:

    58 Query     CREATE TRIGGER `pt_osc_test_zs_del` AFTER DELETE ON `test`.`zs` FOR EACH ROW DELETE IGNORE FROM `test`.`_zs_new` WHERE `test`.`_zs_new`.`id` <=> OLD.`id`
                       58 Query     CREATE TRIGGER `pt_osc_test_zs_upd` AFTER UPDATE ON `test`.`zs` FOR EACH ROW REPLACE INTO `test`.`_zs_new` (`id`, `name`) VALUES (NEW.`id`, NEW.`name`)
                       58 Query     CREATE TRIGGER `pt_osc_test_zs_ins` AFTER INSERT ON `test`.`zs` FOR EACH ROW REPLACE INTO `test`.`_zs_new` (`id`, `name`) VALUES (NEW.`id`, NEW.`name`)

    3.pt-online-schema-change读取原数据表中的记录,所读条数由chunk-size选项确定,将读取的记录复制到_zs_new数据表。

    58 Query     EXPLAIN SELECT * FROM `test`.`zs` WHERE 1=1
                       58 Query     EXPLAIN SELECT `id`, `name` FROM `test`.`zs` LOCK IN SHARE MODE /*explain pt-online-schema-change 13294 copy table*/
                       58 Query     INSERT LOW_PRIORITY IGNORE INTO `test`.`_zs_new` (`id`, `name`) SELECT `id`, `name` FROM `test`.`zs` LOCK IN SHARE MODE /*pt-online-schema-change 13294 copy table*/

    4.用户对原zs数据表执行的DML都会通过触发器自动反映到_zs_new数据表。pt-online-schema-change复制完所有记录后,使用rename将zs表更名为_zs_old,将_zs_new表名修改为zs。rename命令会将多个数据表的更名操作作为一个事物进行处理,所以更名过程中用户的查询不会失败。

    58 Query     SHOW GLOBAL STATUS LIKE 'threads_running'
                       58 Query     ANALYZE TABLE `test`.`_zs_new` /* pt-online-schema-change */
                       58 Query     RENAME TABLE `test`.`zs` TO `test`.`_zs_old`, `test`.`_zs_new` TO `test`.`zs`
                       58 Query     DROP TRIGGER IF EXISTS `test`.`pt_osc_test_zs_del`
                       58 Query     DROP TRIGGER IF EXISTS `test`.`pt_osc_test_zs_upd`
                       58 Query     DROP TRIGGER IF EXISTS `test`.`pt_osc_test_zs_ins`
                       58 Query     SHOW TABLES FROM `test` LIKE '\_zs\_new'

    5.使用pt-online-schema-change应注意

      (1)重复触发器:如果原数据表已经存在AFTER触发器,将无法使用pt-online-schema-change。

      (2)死锁:假设zs数据表的id列有唯一索引(unique index),pt-online-schema-change会使用主键,以内存为单位分割记录,然后将所选范围内的记录复制到_zs_new数据表。这一过程中对_zs_new数据表的主键加排它锁后,为了进行重复检查,还要对id列唯一索引加锁。用户修改的内容(insert、delete、update)也通过触发器应用到_zs_new数据表。但是通过触发器到来的查询会先对id列中创建的唯一索引加排它锁,然后试图再次向主键加锁时,会与pt-online-schema-change进程的以内存块为单位的复制作业产生死锁。

  • 相关阅读:
    Lookup注解
    解决数据量大,分页查询慢的方案
    一个http的请求分析
    MYSQL
    什么是性能优化
    编码规范随笔
    装饰者模式
    单例模式
    J.U.C并发包(1)
    Java内存模型
  • 原文地址:https://www.cnblogs.com/xxmysql/p/5729461.html
Copyright © 2020-2023  润新知