online ddl 工具之pt-online-schema-change封装

一、原理

目前InnoDB引擎是通过以下步骤来进行DDL的:

1 按照原始表(original_table)的表结构和DDL语句,新建一个不可见的临时表(tmp_table)

2 在原表上加write lock,阻塞所有更新操作(insert、delete、update等)

3 执行insert into tmp_table select * from original_table

4 rename original_table和tmp_table,最后drop original_table

5 释放 write lock。

我们可以看见在InnoDB执行DDL的时候,原表是只能读不能写的。

pt-online-schema-change工作原理:

如果表有外键,除非使用 --alter-foreign-keys-method 指定特定的值,否则工具不予执行。

1 创建一个和你要执行 alter 操作的表一样的空表结构。

2 执行表结构修改,然后从原表中的数据到copy到 表结构修改后的表,

3 在原表上创建触发器将 copy 数据的过程中,在原表的更新操作 更新到新表.

   注意:如果表中已经定义了触发器这个工具就不能工作了。

4 copy 完成以后,用rename table 新表代替原表,默认删除原表。

二、依赖

1、操作的表必须有主键。

2、不能rename或者change否则会丢失当前列数据。

  

3、添加字段时只要有not null 就要加default ‘’默认值 否则会报错

三、mysqlha_osc.sh使用方法

 

[root@db72 liding]# ./mysqlha_osc.sh

help:

Please check your input!!!!

options:
-P port
-D databases name
-T type 1=--dry-run 2=--execute 
-S Please input sql 
Can not enter change and rename because Can cause changes to fail
if values not null Time must be added default '0'

内部已经将rename|change 禁用

mysqlha_osc.sh -P 3306 -D test -T 2 -S "alter table test add uname varchar(20)  "

P:port。

D:database name。

T:两个参数 1=--dry-run  2=–execute。

S:sql语句,和数据库正常语法一样。

 


#!/bin/bash

# Author: [email protected]

# Date: 2016-04-27




# helpfunc shows the help info

function helpfunc(){

        echo 

         echo "Please check your input!!!!"

         echo "options:"

         echo " -P      port"

         echo " -D      databases name"

         echo " -T      type 1=--dry-run    2=--execute "

         echo " -S      Please  input sql "


         echo "        Can not enter change and rename because Can cause changes to fail"


         echo "if values   not null Time must be added default '0'"

}

############################################




#get options in command line, cannot be palced in a function

if [ $# -lt 1 ] ;

    then

        helpfunc

         exit 1

else


        while getopts "P:D:T:S:s:" Option

        do

                case $Option in

                        P) port=$OPTARG;;

                        D) database=$OPTARG;;

                        T) type=$OPTARG;;

                        S) sql=$OPTARG;;

                         *) helpfunc; exit 1; ;;

                esac

        done


fi

check_user()

{

                echo "the user is now $person, checkout to 'root' to continue"

}


check_running()

{

                run=`netstat -antp|grep mysql|grep $port`

                if [ -z "$run" ]; then

                   echo "mysql port $port is not running!"

                   exit -1

                fi

}






function main(){

check_user

check_running

sock=/tmp/mysql"$port".sock

. /etc/dbbin/sh_lib/config.sh "/etc/dbbin/conf/mysql.cfg"

admin_user=""#自己定义

admin_pass=`getConfig "mysql" $admin_user`#自己定义

tname=`echo $sql|awk  '{print $3}'`

SQL=`echo $sql|awk -F"$tname" '{print $2}'`


if  echo $SQL | egrep -w "rename|change" ; then

        helpfunc;

        exit 1

else

        if [ $type = 1 ] ;then

                /usr/bin/pt-online-schema-change --user $admin_user --password  $admin_pass --port $port --socket $sock --alter "$SQL" D=$database,t=$tname --dry-run --critical-load="Threads_running=200"

        elif [ $type = 2 ] ;then

                /usr/bin/pt-online-schema-change --user $admin_user --password  $admin_pass --port $port --socket $sock --alter "$SQL" D=$database,t=$tname --execute --critical-load="Threads_running=200"

        else

                helpfunc;

                  exit 1

        fi

fi

}


###############################

main