How to Alter a Column without Locking the Table

advertisement
How to Add a Column without Locking Table
By Will Mayall
24-June-2015
Contents
Overview ................................................................................................................................................... 1
Create a Script................................................................................................................................... 1
The End Result ..................................................................................................................................... 3
Summary ...................................................................................................................................................... 6
Overview
This document is intended to explain the Percona tool
pt-online-schema-change that allows you to add a column
to an existing table without locking the table during
the entire process.
I am assuming you already downloaded the Percona tools
from:
https://www.percona.com/software/percona-toolkit
Create a Script
I general wrap the Percona tools around a script so I
don’t accidently make a typo.
#vi run_online_schema_change.bash
#!/bin/bash
./pt-online-schema-change --execute --ask-pass --user=wam --chunktime=1 --nodrop-old-table --alter "add column foo int(11) default
null" D=d2,t=pers_wam1,h=localhost
1
In the above example, the mysql user = wam, D=the
database or schema, and t=table name. Save the changes
and chmod to 700 so only you can execute the script.
#chmod 700 run_online_schema_change.bash
Then, just execute the script and enter the password!
#./run_online_schema_change.bash
Enter MySQL password:
No slaves found.
See --recursion-method if host lxws2 has slaves.
Not checking slave lag because no slaves were found and --check-slavelag was not specified.
Operation, tries, wait:
copy_rows, 10, 0.25
create_triggers, 10, 1
drop_triggers, 10, 1
swap_tables, 10, 1
update_foreign_keys, 10, 1
Altering `d2`.`pers_wam1`...
Creating new table...
Created new table d2._pers_wam1_new OK.
Altering new table...
Altered `d2`.`_pers_wam1_new` OK.
2015-06-24T10:38:04 Creating triggers...
2015-06-24T10:38:04 Created triggers OK.
2015-06-24T10:38:04 Copying approximately 0 rows...
2015-06-24T10:38:04 Copied rows OK.
2015-06-24T10:38:04 Swapping tables...
2
2015-06-24T10:38:04 Swapped original and new tables OK.
Not dropping old table because --no-drop-old-table was specified.
2015-06-24T10:38:04 Dropping triggers...
2015-06-24T10:38:04 Dropped triggers OK.
Successfully altered `d2`.`pers_wam1`.
#
The End Result
The end result below shows the new column foo has been
added!
mysql> use d2;
Database changed
mysql> show create table pers_wam1\G
*************************** 1. row ***************************
Table: pers_wam1
Create Table: CREATE TABLE `pers_wam1` (
`PERS_ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
`Updated` datetime DEFAULT NULL,
`Deleted` tinyint(1) NOT NULL DEFAULT '0',
`CO_ID` int(10) unsigned DEFAULT NULL,
`LOC_ID` int(10) unsigned DEFAULT NULL,
`Name` varchar(80) DEFAULT NULL,
`Title` varchar(150) DEFAULT NULL,
`MAN_ID` int(10) unsigned DEFAULT '0',
`CAT_ID` int(10) unsigned DEFAULT '0',
`CAT_2` int(10) unsigned DEFAULT '0',
`CAT_3` int(10) unsigned DEFAULT '0',
`CAT_4` int(10) unsigned DEFAULT NULL,
`Reports_To` varchar(80) DEFAULT NULL,
`Phone` varchar(50) NOT NULL DEFAULT '',
3
`Email` varchar(64) NOT NULL DEFAULT '',
`Notes` text,
`other_email` text,
`Source` varchar(80) DEFAULT NULL,
`Sample` tinyint(1) NOT NULL DEFAULT '0',
`NameTitle` varchar(40) DEFAULT NULL,
`Forename` varchar(40) DEFAULT NULL,
`FirstName` varchar(40) DEFAULT NULL,
`MiddleName` varchar(40) DEFAULT NULL,
`NickName` varchar(40) DEFAULT NULL,
`MaidenName` varchar(40) DEFAULT NULL,
`LastName` varchar(40) DEFAULT NULL,
`NameSuffix` varchar(40) DEFAULT NULL,
`Salutation` varchar(40) DEFAULT NULL,
`stamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE
CURRENT_TIMESTAMP,
`department` set('IT','FI','MK') NOT NULL DEFAULT 'IT',
`areacode` varchar(20) DEFAULT NULL,
`reason` varchar(65) DEFAULT NULL,
`editor` int(10) unsigned DEFAULT NULL,
`created` datetime DEFAULT NULL,
`salesforce_id` varchar(45) DEFAULT NULL,
`publicNotes` text,
`linkedinURL` varchar(180) DEFAULT NULL,
`cellPhone` varchar(25) DEFAULT NULL,
`confirmed_reporting` date DEFAULT NULL,
`confirmed_phone` date DEFAULT NULL,
`confirmed_title` date DEFAULT NULL,
`confirmed_email` date DEFAULT NULL,
`reports_to_id` int(10) unsigned DEFAULT NULL,
`reports2cio` tinyint(1) NOT NULL DEFAULT '0',
4
`reports2cfo` tinyint(1) NOT NULL DEFAULT '0',
`twitter` varchar(100) DEFAULT '',
`internalTag` varchar(100) DEFAULT NULL,
`report_updated` date DEFAULT NULL,
`resp_except` text,
`foo` int(11) DEFAULT NULL,
PRIMARY KEY (`PERS_ID`),
UNIQUE KEY `unameco` (`CO_ID`,`Name`,`department`) USING BTREE,
KEY `areacode` (`areacode`),
KEY `CAT_2` (`CAT_2`),
KEY `CAT_3` (`CAT_3`),
KEY `CAT_4` (`CAT_4`),
KEY `CAT_ID` (`CAT_ID`),
KEY `CO_ID` (`CO_ID`),
KEY `confirmed_email` (`confirmed_email`),
KEY `confirmed_phone` (`confirmed_phone`),
KEY `confirmed_reporting` (`confirmed_reporting`),
KEY `department` (`department`),
KEY `Email` (`Email`),
KEY `FirstName` (`FirstName`),
KEY `LastName` (`LastName`),
KEY `linkedinURL` (`linkedinURL`),
KEY `LOC_ID` (`LOC_ID`),
KEY `MAN_ID` (`MAN_ID`),
KEY `Name` (`Name`),
KEY `Phone` (`Phone`),
KEY `Reports_To` (`Reports_To`),
KEY `reports_to_id` (`reports_to_id`),
KEY `Title` (`Title`),
FULLTEXT KEY `ftnametitle` (`Name`,`Title`),
5
FULLTEXT KEY `ftname` (`Name`),
FULLTEXT KEY `fttitle` (`Title`),
FULLTEXT KEY `other_email` (`other_email`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC
1 row in set (0.00 sec)
mysql>
Summary
Using pt-online-schema-change will provide a way to
alter a table while the database is up and functioning
without locking the table during the entire alter
process.
6
Download