MySQL ONLINE DDL 和PT-ONLINE-SCHEMA-CHANGE對比
mysql5.6之前執行ddl語句會執行表鎖,只允許查詢不允許更新,執行ddl主要有兩種方式copy方式和inplace方式,inplace方式又稱為(fast index creation),其中copy方式全稱表鎖,inplace方式只支援二級索引新增和刪除。5.6之後可以利用Online DDL特性完成線上表結構調整,而pt-tools提供的pt-online-schema-change可以在幾乎無表鎖的情況下完成線上表結構調整,這裡就針對mysql做下ddl的過程研究。
mysql原生的ddl方式實現形式有三種,分別是copy table、inplace、online ddl的方式,其中5.1-5.5版本實現是透過copy table的形式,5.6-5.7增加了inplace方式和Online ddl方式。
一、mysql 原生ddl實現方式
copy方式
(1).新建臨時表
(2).鎖原表,禁止DML,允許查詢
(3).將原表資料複製到臨時表(無排序,一行一行複製)
(4).刪除原表,對臨時表進行rename,升級字典鎖,禁止讀寫
(5).完成DDL,釋放鎖
inplace方式
(1).新建索引的資料字典
(2).鎖表,禁止DML,允許查詢
(3).讀取聚集索引,構造新的索引項,排序並插入新索引
(4).等待開啟當前表的所有隻讀事務提交
(5).建立索引結束
online ddl實現
online方式實質也包含了copy和inplace方式,對於不支援online的ddl操作採用copy方式,比如修改列型別,刪除主鍵等;對於inplace方式,mysql內部以“是否修改記錄格式”為基準也分為兩類,一類需要重建表(修改記錄格式),比如新增、刪除列、修改列預設值等;另外一類是隻需要修改表的後設資料,比如新增、刪除索引、修改列名等。Mysql將這兩類方式分別稱為rebuild方式和no-rebuild方式。online ddl主要包括3個階段,prepare階段,ddl執行階段,commit階段,rebuild方式比no-rebuild方式實質多了一個ddl執行階段,prepare階段和commit階段類似。下面將主要介紹ddl執行過程中三個階段的流程。
Prepare階段:
建立新的臨時frm檔案
持有EXCLUSIVE-MDL鎖,禁止讀寫
根據alter型別,確定執行方式(copy,online-rebuild,online-norebuild)
更新資料字典的記憶體物件
分配row_log物件記錄增量
生成新的臨時ibd檔案
ddl執行階段:
降級EXCLUSIVE-MDL鎖,允許讀寫
掃描old_table的聚集索引每一條記錄rec
遍歷新表的聚集索引和二級索引,逐一處理
根據rec構造對應的索引項
將構造索引項插入sort_buffer塊
將sort_buffer塊插入新的索引
處理ddl執行過程中產生的增量(僅rebuild型別需要)
commit階段
升級到EXCLUSIVE-MDL鎖,禁止讀寫
重做最後row_log中最後一部分增量
更新innodb的資料字典表
提交事務(刷事務的redo日誌)
修改統計資訊
rename臨時idb檔案,frm檔案
變更完成
mysql 5.7線上修改表結構案例:
語法
alter table
| ALGORITHM [=] {DEFAULT|INPLACE|COPY}
| ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}
| CHANGE [COLUMN] old_col_name new_col_name column_definition
[FIRST|AFTER col_name]
| LOCK [=] {DEFAULT|NONE|SHARED|EXCLUSIVE}
| MODIFY [COLUMN] col_name column_definition
[FIRST | AFTER col_name]
online ddl的原理是,mysql把在ddl時間內的所有的 插入,更新和刪除操作記錄到一個日誌檔案, 然後再把這些增量資料應用到相應的表上(等表上的事務完全釋放後),這個臨時日誌檔案的上限值由innodb_online_alter_log_max_size指定,每次擴充套件innodb_sort_buffer_size的大小 該引數如果太小有可能導致DDL失敗
二、pt-online-schema-change
注意事項:
(1)表存在主鍵或唯一建
(2)磁碟容量估計
(3)原表不存在觸發器
(4)原表進行批次DML操作時,會有一定影響,需特別注意鎖等待等引數設定
(5)如果更新的表是被子表外來鍵引用的父表,那麼需要相應的更新子表的外來鍵指向
1、online ddl原理
(1)設定mysql會話引數
SET SESSION innodb_lock_wait_timeout=1
SET SESSION lock_wait_timeout=60
SET SESSION wait_timeout=10000
SET @@SQL_QUOTE_SHOW_CREATE = 1,@@SQL_MODE='NO_AUTO_VALUE_ON_ZERO,NO_ENGINE_SUBSTITUTION'
(2)檢查表結構,是否存在主鍵、其他外來鍵參考、觸發器
SHOW TRIGGERS FROM `dbtest` LIKE 't1'
SELECT table_schema, table_name FROM information_schema.key_column_usage WHERE referenced_table_schema='dbtest' AND referenced_table_name='t1'
(3)建立新表
Creating new table...
CREATE TABLE `dbtest`.`_t1_new` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1809061 DEFAULT CHARSET=utf8
Created new table dbtest._t1_new OK.
(4)對新表進行DDL操作
Altering new table...
ALTER TABLE `dbtest`.`_t1_new` ADD COLUMN phone varchar(15)
Altered `dbtest`.`_t1_new` OK.
(5)對舊錶建立觸發器(insert/update/delete)
2017-11-19T18:05:26 Creating triggers...
CREATE TRIGGER `pt_osc_dbtest_t1_del` AFTER DELETE ON `dbtest`.`t1` FOR EACH ROW DELETE IGNORE FROM `dbtest`.`_t1_new` WHERE `dbtest`.`_t1_new`.`id` <=> OLD.`id`
CREATE TRIGGER `pt_osc_dbtest_t1_upd` AFTER UPDATE ON `dbtest`.`t1` FOR EACH ROW REPLACE INTO `dbtest`.`_t1_new` (`id`, `name`) VALUES (NEW.`id`, NEW.`name`)
CREATE TRIGGER `pt_osc_dbtest_t1_ins` AFTER INSERT ON `dbtest`.`t1` FOR EACH ROW REPLACE INTO `dbtest`.`_t1_new` (`id`, `name`) VALUES (NEW.`id`, NEW.`name`)
2017-11-19T18:05:26 Created triggers OK.
(6)copy資料
copy資料一個chunk後會檢查thread_running負載、warning、從庫資訊決定是否繼續copy,預設--chunk-time=0.5,根據這個時間copy的記錄動態調整chunk-size,在Copy相關的chunk時,會對原表相關記錄加S鎖。
2017-11-19T18:05:26 Copying approximately 1593410 rows...
INSERT LOW_PRIORITY IGNORE INTO `dbtest`.`_t1_new` (`id`, `name`) SELECT `id`, `name` FROM `dbtest`.`t1` FORCE INDEX(`PRIMARY`) WHERE ((`id` >= ?)) AND ((`id` <= ?)) LOCK IN SHARE MODE /*pt-online-schema-change 9157 copy nibble*/
SELECT /*!40001 SQL_NO_CACHE */ `id` FROM `dbtest`.`t1` FORCE INDEX(`PRIMARY`) WHERE ((`id` >= ?)) ORDER BY `id` LIMIT ?, 2 /*next chunk boundary*/
2017-11-19T18:05:45 Copied rows OK.
(7)分析新表、統計資訊
2017-11-19T18:05:45 Analyzing new table..
(8)新、舊錶交換,將舊錶t1重新命名為_t1_old,將新表_t1_new重新命名為t1,並刪除舊錶_t1_old
2017-11-19T18:05:45 Swapping tables...
RENAME TABLE `dbtest`.`t1` TO `dbtest`.`_t1_old`, `dbtest`.`_t1_new` TO `dbtest`.`t1`
2017-11-19T18:05:45 Swapped original and new tables OK.
2017-11-19T18:05:45 Dropping old table...
DROP TABLE IF EXISTS `dbtest`.`_t1_old`
2017-11-19T18:05:45 Dropped old table `dbtest`.`_t1_old` OK.
(9)刪除觸發器
2017-11-19T18:05:45 Dropping triggers...
DROP TRIGGER IF EXISTS `dbtest`.`pt_osc_dbtest_t1_del`;
DROP TRIGGER IF EXISTS `dbtest`.`pt_osc_dbtest_t1_upd`;
DROP TRIGGER IF EXISTS `dbtest`.`pt_osc_dbtest_t1_ins`;
2017-11-19T18:05:45 Dropped triggers OK.
(10)完成表結構線上修改
Successfully altered `dbtest`.`t1`.
2、增加字段
預執行:pt-online-schema-change --user=dbuser --password=123456 --host=10.xx --alter "ADD COLUMN phone varchar(15)" D=dbtest,t=t1 --print --dry-run
正式執行:pt-online-schema-change --user=dbuser --password=123456
--host=10.xx --alter "ADD COLUMN phone varchar(15)" D=dbtest,t=t1
--print --execute
3、刪除欄位
pt-online-schema-change --user=dbuser --password=123456 --host=10.xx --no-check-replication-filters --recursion-method=none --alter "DROP COLUMN phone " D=dbtest,t=t1 --print --execute
4、添加索引
pt-online-schema-change --user=dbuser --password=123456 --host=10.xx --no-check-replication-filters --recursion-method=none --alter "add key idx_name(name)" D=dbtest,t=t1 --print --execute
5、刪除索引
pt-online-schema-change --user=dbuser --password=123456 --host=10.xx --no-check-replication-filters --recursion-method=none --alter "DROP key idx_name" D=dbtest,t=t1 --print --execute
6、改變欄位型別、長度
pt-online-schema-change --user=dbuser --password=123456 --host=10.xx --no-check-replication-filters --recursion-method=none --alter "modify name varchar(10)" D=dbtest,t=t1 --print --execute
mysql原生的ddl方式實現形式有三種,分別是copy table、inplace、online ddl的方式,其中5.1-5.5版本實現是透過copy table的形式,5.6-5.7增加了inplace方式和Online ddl方式。
一、mysql 原生ddl實現方式
copy方式
(1).新建臨時表
(2).鎖原表,禁止DML,允許查詢
(3).將原表資料複製到臨時表(無排序,一行一行複製)
(4).刪除原表,對臨時表進行rename,升級字典鎖,禁止讀寫
(5).完成DDL,釋放鎖
inplace方式
(1).新建索引的資料字典
(2).鎖表,禁止DML,允許查詢
(3).讀取聚集索引,構造新的索引項,排序並插入新索引
(4).等待開啟當前表的所有隻讀事務提交
(5).建立索引結束
online ddl實現
online方式實質也包含了copy和inplace方式,對於不支援online的ddl操作採用copy方式,比如修改列型別,刪除主鍵等;對於inplace方式,mysql內部以“是否修改記錄格式”為基準也分為兩類,一類需要重建表(修改記錄格式),比如新增、刪除列、修改列預設值等;另外一類是隻需要修改表的後設資料,比如新增、刪除索引、修改列名等。Mysql將這兩類方式分別稱為rebuild方式和no-rebuild方式。online ddl主要包括3個階段,prepare階段,ddl執行階段,commit階段,rebuild方式比no-rebuild方式實質多了一個ddl執行階段,prepare階段和commit階段類似。下面將主要介紹ddl執行過程中三個階段的流程。
Prepare階段:
建立新的臨時frm檔案
持有EXCLUSIVE-MDL鎖,禁止讀寫
根據alter型別,確定執行方式(copy,online-rebuild,online-norebuild)
更新資料字典的記憶體物件
分配row_log物件記錄增量
生成新的臨時ibd檔案
ddl執行階段:
降級EXCLUSIVE-MDL鎖,允許讀寫
掃描old_table的聚集索引每一條記錄rec
遍歷新表的聚集索引和二級索引,逐一處理
根據rec構造對應的索引項
將構造索引項插入sort_buffer塊
將sort_buffer塊插入新的索引
處理ddl執行過程中產生的增量(僅rebuild型別需要)
commit階段
升級到EXCLUSIVE-MDL鎖,禁止讀寫
重做最後row_log中最後一部分增量
更新innodb的資料字典表
提交事務(刷事務的redo日誌)
修改統計資訊
rename臨時idb檔案,frm檔案
變更完成
Operation | In-Place? | Copies Table? | Allows Concurrent DML? | Allows Concurrent Query? | Notes |
---|---|---|---|---|---|
新增索引 | Yes* | No* | Yes | Yes | 對全文索引的一些限制 |
刪除索引 | Yes | No | Yes | Yes | 僅修改表的後設資料 |
OPTIMIZE TABLE | Yes | Yes | Yes | Yes | 從 5.6.17開始使用ALGORITHM=INPLACE,當然如果指定了old_alter_table=1或mysqld啟動帶--skip-new則將還是COPY模式。如果表上有全文索引只支援COPY |
對一列設定預設值 | Yes | No | Yes | Yes | 僅修改表的後設資料 |
對一列修改auto-increment 的值 | Yes | No | Yes | Yes | 僅修改表的後設資料 |
新增 foreign key constraint | Yes* | No* | Yes | Yes | 為了避免複製表,在約束建立時會禁用foreign_key_checks |
刪除 foreign key constraint | Yes | No | Yes | Yes | foreign_key_checks 不影響 |
改變列名 | Yes* | No* | Yes* | Yes | 為了允許DML併發, 如果保持相同資料型別,僅改變列名 |
新增列 | Yes* | Yes* | Yes* | Yes | 儘管允許 ALGORITHM=INPLACE ,但資料大幅重組,所以它仍然是一項昂貴的操作。當新增列是auto-increment,不允許DML併發 |
刪除列 | Yes | Yes* | Yes | Yes | 儘管允許 ALGORITHM=INPLACE ,但資料大幅重組,所以它仍然是一項昂貴的操作 |
修改列資料型別 | No | Yes* | No | Yes | 修改型別或新增長度,都會複製表,而且不允許更新操作 |
更改列順序 | Yes | Yes | Yes | Yes | 儘管允許 ALGORITHM=INPLACE ,但資料大幅重組,所以它仍然是一項昂貴的操作 |
修改ROW_FORMAT 和KEY_BLOCK_SIZE |
Yes | Yes | Yes | Yes | 儘管允許 ALGORITHM=INPLACE ,但資料大幅重組,所以它仍然是一項昂貴的操作 |
設定列屬性NULL 或NOT NULL |
Yes | Yes | Yes | Yes | 儘管允許 ALGORITHM=INPLACE ,但資料大幅重組,所以它仍然是一項昂貴的操作 |
新增主鍵 | Yes* | Yes | Yes | Yes |
儘管允許 ALGORITHM=INPLACE ,但資料大幅重組,所以它仍然是一項昂貴的操作。 如果列定義必須轉化NOT NULL,則不允許INPLACE |
刪除並新增主鍵 | Yes | Yes | Yes | Yes | 在同一個 ALTER TABLE 語句刪除就主鍵、新增新主鍵時,才允許inplace;資料大幅重組,所以它仍然是一項昂貴的操作。 |
刪除主鍵 | No | Yes | No | Yes | 不允許併發DML,要複製表,而且如果沒有在同一 ATLER TABLE 語句裡同時新增主鍵則會收到限制 |
變更表字符集 | No | Yes | No | Yes | 如果新的字符集編碼不同,重建表 |
mysql 5.7線上修改表結構案例:
語法
alter table
| ALGORITHM [=] {DEFAULT|INPLACE|COPY}
| ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}
| CHANGE [COLUMN] old_col_name new_col_name column_definition
[FIRST|AFTER col_name]
| LOCK [=] {DEFAULT|NONE|SHARED|EXCLUSIVE}
| MODIFY [COLUMN] col_name column_definition
[FIRST | AFTER col_name]
online ddl的原理是,mysql把在ddl時間內的所有的 插入,更新和刪除操作記錄到一個日誌檔案, 然後再把這些增量資料應用到相應的表上(等表上的事務完全釋放後),這個臨時日誌檔案的上限值由innodb_online_alter_log_max_size指定,每次擴充套件innodb_sort_buffer_size的大小 該引數如果太小有可能導致DDL失敗
二、pt-online-schema-change
注意事項:
(1)表存在主鍵或唯一建
(2)磁碟容量估計
(3)原表不存在觸發器
(4)原表進行批次DML操作時,會有一定影響,需特別注意鎖等待等引數設定
(5)如果更新的表是被子表外來鍵引用的父表,那麼需要相應的更新子表的外來鍵指向
1、online ddl原理
(1)設定mysql會話引數
SET SESSION innodb_lock_wait_timeout=1
SET SESSION lock_wait_timeout=60
SET SESSION wait_timeout=10000
SET @@SQL_QUOTE_SHOW_CREATE = 1,@@SQL_MODE='NO_AUTO_VALUE_ON_ZERO,NO_ENGINE_SUBSTITUTION'
(2)檢查表結構,是否存在主鍵、其他外來鍵參考、觸發器
SHOW TRIGGERS FROM `dbtest` LIKE 't1'
SELECT table_schema, table_name FROM information_schema.key_column_usage WHERE referenced_table_schema='dbtest' AND referenced_table_name='t1'
(3)建立新表
Creating new table...
CREATE TABLE `dbtest`.`_t1_new` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1809061 DEFAULT CHARSET=utf8
Created new table dbtest._t1_new OK.
(4)對新表進行DDL操作
Altering new table...
ALTER TABLE `dbtest`.`_t1_new` ADD COLUMN phone varchar(15)
Altered `dbtest`.`_t1_new` OK.
(5)對舊錶建立觸發器(insert/update/delete)
2017-11-19T18:05:26 Creating triggers...
CREATE TRIGGER `pt_osc_dbtest_t1_del` AFTER DELETE ON `dbtest`.`t1` FOR EACH ROW DELETE IGNORE FROM `dbtest`.`_t1_new` WHERE `dbtest`.`_t1_new`.`id` <=> OLD.`id`
CREATE TRIGGER `pt_osc_dbtest_t1_upd` AFTER UPDATE ON `dbtest`.`t1` FOR EACH ROW REPLACE INTO `dbtest`.`_t1_new` (`id`, `name`) VALUES (NEW.`id`, NEW.`name`)
CREATE TRIGGER `pt_osc_dbtest_t1_ins` AFTER INSERT ON `dbtest`.`t1` FOR EACH ROW REPLACE INTO `dbtest`.`_t1_new` (`id`, `name`) VALUES (NEW.`id`, NEW.`name`)
2017-11-19T18:05:26 Created triggers OK.
(6)copy資料
copy資料一個chunk後會檢查thread_running負載、warning、從庫資訊決定是否繼續copy,預設--chunk-time=0.5,根據這個時間copy的記錄動態調整chunk-size,在Copy相關的chunk時,會對原表相關記錄加S鎖。
2017-11-19T18:05:26 Copying approximately 1593410 rows...
INSERT LOW_PRIORITY IGNORE INTO `dbtest`.`_t1_new` (`id`, `name`) SELECT `id`, `name` FROM `dbtest`.`t1` FORCE INDEX(`PRIMARY`) WHERE ((`id` >= ?)) AND ((`id` <= ?)) LOCK IN SHARE MODE /*pt-online-schema-change 9157 copy nibble*/
SELECT /*!40001 SQL_NO_CACHE */ `id` FROM `dbtest`.`t1` FORCE INDEX(`PRIMARY`) WHERE ((`id` >= ?)) ORDER BY `id` LIMIT ?, 2 /*next chunk boundary*/
2017-11-19T18:05:45 Copied rows OK.
(7)分析新表、統計資訊
2017-11-19T18:05:45 Analyzing new table..
(8)新、舊錶交換,將舊錶t1重新命名為_t1_old,將新表_t1_new重新命名為t1,並刪除舊錶_t1_old
2017-11-19T18:05:45 Swapping tables...
RENAME TABLE `dbtest`.`t1` TO `dbtest`.`_t1_old`, `dbtest`.`_t1_new` TO `dbtest`.`t1`
2017-11-19T18:05:45 Swapped original and new tables OK.
2017-11-19T18:05:45 Dropping old table...
DROP TABLE IF EXISTS `dbtest`.`_t1_old`
2017-11-19T18:05:45 Dropped old table `dbtest`.`_t1_old` OK.
(9)刪除觸發器
2017-11-19T18:05:45 Dropping triggers...
DROP TRIGGER IF EXISTS `dbtest`.`pt_osc_dbtest_t1_del`;
DROP TRIGGER IF EXISTS `dbtest`.`pt_osc_dbtest_t1_upd`;
DROP TRIGGER IF EXISTS `dbtest`.`pt_osc_dbtest_t1_ins`;
2017-11-19T18:05:45 Dropped triggers OK.
(10)完成表結構線上修改
Successfully altered `dbtest`.`t1`.
點選(此處)摺疊或開啟
-
171119 17:53:00 66 Connect dbuser@BX-128-28 on dbtest
-
66 Query SHOW VARIABLES LIKE 'innodb\_lock_wait_timeout'
-
66 Query SET SESSION innodb_lock_wait_timeout=1
-
66 Query SHOW VARIABLES LIKE 'lock\_wait_timeout'
-
66 Query SET SESSION lock_wait_timeout=60
-
66 Query SHOW VARIABLES LIKE 'wait\_timeout'
-
66 Query SET SESSION wait_timeout=10000
-
66 Query SELECT @@SQL_MODE
-
66 Query SET @@SQL_QUOTE_SHOW_CREATE = 1/*!40101, @@SQL_MODE='NO_AUTO_VALUE_ON_ZERO,NO_ENGINE_SUBSTITUTION'*/
-
66 Query SELECT @@server_id /*!50038 , @@hostname*/
-
67 Connect dbuser@BX-128-28 on dbtest
-
67 Query SHOW VARIABLES LIKE 'innodb\_lock_wait_timeout'
-
67 Query SET SESSION innodb_lock_wait_timeout=1
-
67 Query SHOW VARIABLES LIKE 'lock\_wait_timeout'
-
67 Query SET SESSION lock_wait_timeout=60
-
67 Query SHOW VARIABLES LIKE 'wait\_timeout'
-
67 Query SET SESSION wait_timeout=10000
-
67 Query SELECT @@SQL_MODE
-
67 Query SET @@SQL_QUOTE_SHOW_CREATE = 1/*!40101, @@SQL_MODE='NO_AUTO_VALUE_ON_ZERO,NO_ENGINE_SUBSTITUTION'*/
-
67 Query SELECT @@server_id /*!50038 , @@hostname*/
-
66 Query SHOW VARIABLES LIKE 'wsrep_on'
-
66 Query SHOW VARIABLES LIKE 'version%'
-
66 Query SHOW ENGINES
-
66 Query SHOW VARIABLES LIKE 'innodb_version'
-
66 Query SHOW VARIABLES LIKE 'innodb_stats_persistent'
-
66 Query SELECT CONCAT(@@hostname, @@port)
-
66 Query SHOW TABLES FROM `dbtest` LIKE 't1'
-
66 Query SHOW TRIGGERS FROM `dbtest` LIKE 't1'
-
66 Query /*!40101 SET @OLD_SQL_MODE := @@SQL_MODE, @@SQL_MODE := '', @OLD_QUOTE := @@SQL_QUOTE_SHOW_CREATE, @@SQL_QUOTE_SHOW_CREATE := 1 */
-
66 Query USE `dbtest`
-
66 Query SHOW CREATE TABLE `dbtest`.`t1`
-
66 Query /*!40101 SET @@SQL_MODE := @OLD_SQL_MODE, @@SQL_QUOTE_SHOW_CREATE := @OLD_QUOTE */
-
66 Query EXPLAIN SELECT * FROM `dbtest`.`t1` WHERE 1=1
-
66 Query SELECT table_schema, table_name FROM information_schema.key_column_usage WHERE referenced_table_schema='dbtest' AND referenced_table_name='t1'
-
66 Query SHOW VARIABLES LIKE 'wsrep_on'
-
66 Query /*!40101 SET @OLD_SQL_MODE := @@SQL_MODE, @@SQL_MODE := '', @OLD_QUOTE := @@SQL_QUOTE_SHOW_CREATE, @@SQL_QUOTE_SHOW_CREATE := 1 */
-
66 Query USE `dbtest`
-
66 Query SHOW CREATE TABLE `dbtest`.`t1`
-
66 Query /*!40101 SET @@SQL_MODE := @OLD_SQL_MODE, @@SQL_QUOTE_SHOW_CREATE := @OLD_QUOTE */
-
66 Query CREATE TABLE `dbtest`.`_t1_new` (
-
`id` int(11) NOT NULL AUTO_INCREMENT,
-
`name` varchar(30) DEFAULT NULL,
-
PRIMARY KEY (`id`)
-
) ENGINE=InnoDB AUTO_INCREMENT=1809061 DEFAULT CHARSET=utf8
-
66 Query ALTER TABLE `dbtest`.`_t1_new` ADD COLUMN phone varchar(15)
-
66 Query /*!40101 SET @OLD_SQL_MODE := @@SQL_MODE, @@SQL_MODE := '', @OLD_QUOTE := @@SQL_QUOTE_SHOW_CREATE, @@SQL_QUOTE_SHOW_CREATE := 1 */
-
66 Query USE `dbtest`
-
66 Query SHOW CREATE TABLE `dbtest`.`_t1_new`
-
66 Query /*!40101 SET @@SQL_MODE := @OLD_SQL_MODE, @@SQL_QUOTE_SHOW_CREATE := @OLD_QUOTE */
-
66 Query EXPLAIN SELECT * FROM `dbtest`.`t1` WHERE 1=1
-
66 Query SELECT /*!40001 SQL_NO_CACHE */ `id` FROM `dbtest`.`t1` FORCE INDEX(`PRIMARY`) ORDER BY `id` LIMIT 1 /*first lower boundary*/
-
66 Query SHOW TABLES FROM `dbtest` LIKE '\_t1\_new'
-
66 Query DROP TABLE IF EXISTS `dbtest`.`_t1_new`
-
67 Quit
- 66 Quit
預執行:pt-online-schema-change --user=dbuser --password=123456 --host=10.xx --alter "ADD COLUMN phone varchar(15)" D=dbtest,t=t1 --print --dry-run
點選(此處)摺疊或開啟
-
Operation, tries, wait:
-
analyze_table, 10, 1
-
copy_rows, 10, 0.25
-
create_triggers, 10, 1
-
drop_triggers, 10, 1
-
swap_tables, 10, 1
-
update_foreign_keys, 10, 1
-
Starting a dry run. `dbtest`.`t1` will not be altered. Specify --execute instead of --dry-run to alter the table.
-
Creating new table...
-
CREATE TABLE `dbtest`.`_t1_new` (
-
`id` int(11) NOT NULL AUTO_INCREMENT,
-
`name` varchar(30) DEFAULT NULL,
-
PRIMARY KEY (`id`)
-
) ENGINE=InnoDB AUTO_INCREMENT=1809061 DEFAULT CHARSET=utf8
-
Created new table dbtest._t1_new OK.
-
Altering new table...
-
ALTER TABLE `dbtest`.`_t1_new` ADD COLUMN phone varchar(15)
-
Altered `dbtest`.`_t1_new` OK.
-
Not creating triggers because this is a dry run.
-
CREATE TRIGGER `pt_osc_dbtest_t1_del` AFTER DELETE ON `dbtest`.`t1` FOR EACH ROW DELETE IGNORE FROM `dbtest`.`_t1_new` WHERE `dbtest`.`_t1_new`.`id` <=> OLD.`id`
-
CREATE TRIGGER `pt_osc_dbtest_t1_upd` AFTER UPDATE ON `dbtest`.`t1` FOR EACH ROW REPLACE INTO `dbtest`.`_t1_new` (`id`, `name`) VALUES (NEW.`id`, NEW.`name`)
-
CREATE TRIGGER `pt_osc_dbtest_t1_ins` AFTER INSERT ON `dbtest`.`t1` FOR EACH ROW REPLACE INTO `dbtest`.`_t1_new` (`id`, `name`) VALUES (NEW.`id`, NEW.`name`)
-
Not copying rows because this is a dry run.
-
INSERT LOW_PRIORITY IGNORE INTO `dbtest`.`_t1_new` (`id`, `name`) SELECT `id`, `name` FROM `dbtest`.`t1` FORCE INDEX(`PRIMARY`) WHERE ((`id` >= ?)) AND ((`id` <= ?)) LOCK IN SHARE MODE /*pt-online-schema-change 9137 copy nibble*/
-
SELECT /*!40001 SQL_NO_CACHE */ `id` FROM `dbtest`.`t1` FORCE INDEX(`PRIMARY`) WHERE ((`id` >= ?)) ORDER BY `id` LIMIT ?, 2 /*next chunk boundary*/
-
Not swapping tables because this is a dry run.
-
Not dropping old table because this is a dry run.
-
Not dropping triggers because this is a dry run.
-
DROP TRIGGER IF EXISTS `dbtest`.`pt_osc_dbtest_t1_del`;
-
DROP TRIGGER IF EXISTS `dbtest`.`pt_osc_dbtest_t1_upd`;
-
DROP TRIGGER IF EXISTS `dbtest`.`pt_osc_dbtest_t1_ins`;
-
2017-11-19T17:53:00 Dropping new table...
-
DROP TABLE IF EXISTS `dbtest`.`_t1_new`;
-
2017-11-19T17:53:00 Dropped new table OK.
- Dry run complete. `dbtest`.`t1` was not altered.
點選(此處)摺疊或開啟
-
No slaves found. See --recursion-method if host BX-128-28 has slaves.
-
Not checking slave lag because no slaves were found and --check-slave-lag was not specified.
-
Operation, tries, wait:
-
analyze_table, 10, 1
-
copy_rows, 10, 0.25
-
create_triggers, 10, 1
-
drop_triggers, 10, 1
-
swap_tables, 10, 1
-
update_foreign_keys, 10, 1
-
Altering `dbtest`.`t1`...
-
Creating new table...
-
CREATE TABLE `dbtest`.`_t1_new` (
-
`id` int(11) NOT NULL AUTO_INCREMENT,
-
`name` varchar(30) DEFAULT NULL,
-
PRIMARY KEY (`id`)
-
) ENGINE=InnoDB AUTO_INCREMENT=1809061 DEFAULT CHARSET=utf8
-
Created new table dbtest._t1_new OK.
-
Altering new table...
-
ALTER TABLE `dbtest`.`_t1_new` ADD COLUMN phone varchar(15)
-
Altered `dbtest`.`_t1_new` OK.
-
2017-11-19T18:05:26 Creating triggers...
-
CREATE TRIGGER `pt_osc_dbtest_t1_del` AFTER DELETE ON `dbtest`.`t1` FOR EACH ROW DELETE IGNORE FROM `dbtest`.`_t1_new` WHERE `dbtest`.`_t1_new`.`id` <=> OLD.`id`
-
CREATE TRIGGER `pt_osc_dbtest_t1_upd` AFTER UPDATE ON `dbtest`.`t1` FOR EACH ROW REPLACE INTO `dbtest`.`_t1_new` (`id`, `name`) VALUES (NEW.`id`, NEW.`name`)
-
CREATE TRIGGER `pt_osc_dbtest_t1_ins` AFTER INSERT ON `dbtest`.`t1` FOR EACH ROW REPLACE INTO `dbtest`.`_t1_new` (`id`, `name`) VALUES (NEW.`id`, NEW.`name`)
-
2017-11-19T18:05:26 Created triggers OK.
-
2017-11-19T18:05:26 Copying approximately 1593410 rows...
-
INSERT LOW_PRIORITY IGNORE INTO `dbtest`.`_t1_new` (`id`, `name`) SELECT `id`, `name` FROM `dbtest`.`t1` FORCE INDEX(`PRIMARY`) WHERE ((`id` >= ?)) AND ((`id` <= ?)) LOCK IN SHARE MODE /*pt-online-schema-change 9157 copy nibble*/
-
SELECT /*!40001 SQL_NO_CACHE */ `id` FROM `dbtest`.`t1` FORCE INDEX(`PRIMARY`) WHERE ((`id` >= ?)) ORDER BY `id` LIMIT ?, 2 /*next chunk boundary*/
-
2017-11-19T18:05:45 Copied rows OK.
-
2017-11-19T18:05:45 Analyzing new table...
-
2017-11-19T18:05:45 Swapping tables...
-
RENAME TABLE `dbtest`.`t1` TO `dbtest`.`_t1_old`, `dbtest`.`_t1_new` TO `dbtest`.`t1`
-
2017-11-19T18:05:45 Swapped original and new tables OK.
-
2017-11-19T18:05:45 Dropping old table...
-
DROP TABLE IF EXISTS `dbtest`.`_t1_old`
-
2017-11-19T18:05:45 Dropped old table `dbtest`.`_t1_old` OK.
-
2017-11-19T18:05:45 Dropping triggers...
-
DROP TRIGGER IF EXISTS `dbtest`.`pt_osc_dbtest_t1_del`;
-
DROP TRIGGER IF EXISTS `dbtest`.`pt_osc_dbtest_t1_upd`;
-
DROP TRIGGER IF EXISTS `dbtest`.`pt_osc_dbtest_t1_ins`;
-
2017-11-19T18:05:45 Dropped triggers OK.
- Successfully altered `dbtest`.`t1`.
pt-online-schema-change --user=dbuser --password=123456 --host=10.xx --no-check-replication-filters --recursion-method=none --alter "DROP COLUMN phone " D=dbtest,t=t1 --print --execute
點選(此處)摺疊或開啟
-
No slaves found. See --recursion-method if host BX-128-28 has slaves.
-
Not checking slave lag because no slaves were found and --check-slave-lag was not specified.
-
Operation, tries, wait:
-
analyze_table, 10, 1
-
copy_rows, 10, 0.25
-
create_triggers, 10, 1
-
drop_triggers, 10, 1
-
swap_tables, 10, 1
-
update_foreign_keys, 10, 1
-
Altering `dbtest`.`t1`...
-
Creating new table...
-
CREATE TABLE `dbtest`.`_t1_new` (
-
`id` int(11) NOT NULL AUTO_INCREMENT,
-
`name` varchar(30) DEFAULT NULL,
-
`phone` varchar(15) DEFAULT NULL,
-
PRIMARY KEY (`id`)
-
) ENGINE=InnoDB AUTO_INCREMENT=1809061 DEFAULT CHARSET=utf8
-
Created new table dbtest._t1_new OK.
-
Altering new table...
-
ALTER TABLE `dbtest`.`_t1_new` DROP COLUMN phone
-
Altered `dbtest`.`_t1_new` OK.
-
2017-11-19T22:56:33 Creating triggers...
-
CREATE TRIGGER `pt_osc_dbtest_t1_del` AFTER DELETE ON `dbtest`.`t1` FOR EACH ROW DELETE IGNORE FROM `dbtest`.`_t1_new` WHERE `dbtest`.`_t1_new`.`id` <=> OLD.`id`
-
CREATE TRIGGER `pt_osc_dbtest_t1_upd` AFTER UPDATE ON `dbtest`.`t1` FOR EACH ROW REPLACE INTO `dbtest`.`_t1_new` (`id`, `name`) VALUES (NEW.`id`, NEW.`name`)
-
CREATE TRIGGER `pt_osc_dbtest_t1_ins` AFTER INSERT ON `dbtest`.`t1` FOR EACH ROW REPLACE INTO `dbtest`.`_t1_new` (`id`, `name`) VALUES (NEW.`id`, NEW.`name`)
-
2017-11-19T22:56:33 Created triggers OK.
-
2017-11-19T22:56:33 Copying approximately 1597892 rows...
-
INSERT LOW_PRIORITY IGNORE INTO `dbtest`.`_t1_new` (`id`, `name`) SELECT `id`, `name` FROM `dbtest`.`t1` FORCE INDEX(`PRIMARY`) WHERE ((`id` >= ?)) AND ((`id` <= ?)) LOCK IN SHARE MODE /*pt-online-schema-change 9444 copy nibble*/
-
SELECT /*!40001 SQL_NO_CACHE */ `id` FROM `dbtest`.`t1` FORCE INDEX(`PRIMARY`) WHERE ((`id` >= ?)) ORDER BY `id` LIMIT ?, 2 /*next chunk boundary*/
-
2017-11-19T22:56:52 Copied rows OK.
-
2017-11-19T22:56:52 Analyzing new table...
-
2017-11-19T22:56:52 Swapping tables...
-
RENAME TABLE `dbtest`.`t1` TO `dbtest`.`_t1_old`, `dbtest`.`_t1_new` TO `dbtest`.`t1`
-
2017-11-19T22:56:52 Swapped original and new tables OK.
-
2017-11-19T22:56:52 Dropping old table...
-
DROP TABLE IF EXISTS `dbtest`.`_t1_old`
-
2017-11-19T22:56:52 Dropped old table `dbtest`.`_t1_old` OK.
-
2017-11-19T22:56:52 Dropping triggers...
-
DROP TRIGGER IF EXISTS `dbtest`.`pt_osc_dbtest_t1_del`;
-
DROP TRIGGER IF EXISTS `dbtest`.`pt_osc_dbtest_t1_upd`;
-
DROP TRIGGER IF EXISTS `dbtest`.`pt_osc_dbtest_t1_ins`;
-
2017-11-19T22:56:52 Dropped triggers OK.
- Successfully altered `dbtest`.`t1`.
pt-online-schema-change --user=dbuser --password=123456 --host=10.xx --no-check-replication-filters --recursion-method=none --alter "add key idx_name(name)" D=dbtest,t=t1 --print --execute
點選(此處)摺疊或開啟
-
No slaves found. See --recursion-method if host BX-128-28 has slaves.
-
Not checking slave lag because no slaves were found and --check-slave-lag was not specified.
-
Operation, tries, wait:
-
analyze_table, 10, 1
-
copy_rows, 10, 0.25
-
create_triggers, 10, 1
-
drop_triggers, 10, 1
-
swap_tables, 10, 1
-
update_foreign_keys, 10, 1
-
Altering `dbtest`.`t1`...
-
Creating new table...
-
CREATE TABLE `dbtest`.`_t1_new` (
-
`id` int(11) NOT NULL AUTO_INCREMENT,
-
`name` varchar(30) DEFAULT NULL,
-
PRIMARY KEY (`id`)
-
) ENGINE=InnoDB AUTO_INCREMENT=1809061 DEFAULT CHARSET=utf8
-
Created new table dbtest._t1_new OK.
-
Altering new table...
-
ALTER TABLE `dbtest`.`_t1_new` add key(name)
-
Altered `dbtest`.`_t1_new` OK.
-
2017-11-19T23:00:40 Creating triggers...
-
CREATE TRIGGER `pt_osc_dbtest_t1_del` AFTER DELETE ON `dbtest`.`t1` FOR EACH ROW DELETE IGNORE FROM `dbtest`.`_t1_new` WHERE `dbtest`.`_t1_new`.`id` <=> OLD.`id`
-
CREATE TRIGGER `pt_osc_dbtest_t1_upd` AFTER UPDATE ON `dbtest`.`t1` FOR EACH ROW REPLACE INTO `dbtest`.`_t1_new` (`id`, `name`) VALUES (NEW.`id`, NEW.`name`)
-
CREATE TRIGGER `pt_osc_dbtest_t1_ins` AFTER INSERT ON `dbtest`.`t1` FOR EACH ROW REPLACE INTO `dbtest`.`_t1_new` (`id`, `name`) VALUES (NEW.`id`, NEW.`name`)
-
2017-11-19T23:00:40 Created triggers OK.
-
2017-11-19T23:00:40 Copying approximately 1559718 rows...
-
INSERT LOW_PRIORITY IGNORE INTO `dbtest`.`_t1_new` (`id`, `name`) SELECT `id`, `name` FROM `dbtest`.`t1` FORCE INDEX(`PRIMARY`) WHERE ((`id` >= ?)) AND ((`id` <= ?)) LOCK IN SHARE MODE /*pt-online-schema-change 9453 copy nibble*/
-
SELECT /*!40001 SQL_NO_CACHE */ `id` FROM `dbtest`.`t1` FORCE INDEX(`PRIMARY`) WHERE ((`id` >= ?)) ORDER BY `id` LIMIT ?, 2 /*next chunk boundary*/
-
2017-11-19T23:01:09 Copied rows OK.
-
2017-11-19T23:01:09 Analyzing new table...
-
2017-11-19T23:01:09 Swapping tables...
-
RENAME TABLE `dbtest`.`t1` TO `dbtest`.`_t1_old`, `dbtest`.`_t1_new` TO `dbtest`.`t1`
-
2017-11-19T23:01:09 Swapped original and new tables OK.
-
2017-11-19T23:01:09 Dropping old table...
-
DROP TABLE IF EXISTS `dbtest`.`_t1_old`
-
2017-11-19T23:01:09 Dropped old table `dbtest`.`_t1_old` OK.
-
2017-11-19T23:01:09 Dropping triggers...
-
DROP TRIGGER IF EXISTS `dbtest`.`pt_osc_dbtest_t1_del`;
-
DROP TRIGGER IF EXISTS `dbtest`.`pt_osc_dbtest_t1_upd`;
-
DROP TRIGGER IF EXISTS `dbtest`.`pt_osc_dbtest_t1_ins`;
-
2017-11-19T23:01:09 Dropped triggers OK.
- Successfully altered `dbtest`.`t1`.
pt-online-schema-change --user=dbuser --password=123456 --host=10.xx --no-check-replication-filters --recursion-method=none --alter "DROP key idx_name" D=dbtest,t=t1 --print --execute
6、改變欄位型別、長度
pt-online-schema-change --user=dbuser --password=123456 --host=10.xx --no-check-replication-filters --recursion-method=none --alter "modify name varchar(10)" D=dbtest,t=t1 --print --execute
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/27067062/viewspace-2147452/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 一個 MySQL 線上 DDL 工具 — pt-online-schema-changeMySql
- MySQL Online DDL詳解MySql
- MySQL 5.7使用pt-online-schema-change對大表加索引MySql索引
- MySQL DDL執行方式-Online DDL介紹MySql
- MySQL 5.7使用pt-online-schema-change對大表加欄位MySql
- pt-online-schema-change和XtraBackup的
- mysql之 openark-kit online ddlMySql
- MySQL & MariaDB Online DDL 參考指南MySql
- MySQL修改大表工具pt-online-schema-change原理MySql
- MySQL:pt-online-schema-change原理及注意點(未完)MySql
- MySQL 執行 Online DDL 操作報錯空間不足?MySql
- MySQL Online DDL導致全域性鎖表案例分析MySql
- pt-online-schema-change工作過程介紹
- pt-online-schema-change使用引數說明
- pt-online-schema-change 錯誤集 Wide characterIDE
- MySQL在其版本迭代後Online DDL功能發生了哪些變化?MySql
- 線上改表工具oak-online-alter-table和pt-online-schema-change的使用限制總結
- 對比上次MySQL的DDLMySql
- MySQL 5.6使用pt-online-schema-change線上修改大表欄位長度MySql
- MySQL 8.0 Reference Manual(讀書筆記81節-- InnoDB and Online DDL (1))MySql筆記
- MySQL 8.0 Reference Manual(讀書筆記82節-- InnoDB and Online DDL (2))MySql筆記
- MySQL 8.0 Reference Manual(讀書筆記83節-- InnoDB and Online DDL (3))MySql筆記
- MySQL 8.0 Reference Manual(讀書筆記84節-- InnoDB and Online DDL (4))MySql筆記
- 記錄一次 Online DDL 操作
- TIDB和MySQL效能對比TiDBMySql
- MySQL的DDL和DML操作語法MySql
- PostgreSQL 資料庫結構(DDL)比對工具 pgquarrelSQL資料庫
- MySQL(十三)DDL之庫和表的管理MySql
- MySQL DDL操作表MySql
- TiDB Online DDL 在 TiCDC 中的應用丨TiDB 工具分享TiDB
- MySQL 資料對比MySql
- Oracle和MySQL資料庫CTAS等操作對比OracleMySql資料庫
- mysql的DDL操作對業務產生影響測試MySql
- MYSQL引擎的鎖對比MySql
- MySQL三種InnoDB、MyISAM和MEMORY儲存引擎對比MySql儲存引擎
- PG和MySQL詳細的一些特性對比MySql
- python date 和 datetime 的取值範圍(對比 Mysql 的 datetime 和 timestamp)PythonMySql
- MySQL高可用架構對比MySql架構
- MySQL 半同步 與Raft對比MySqlRaft