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