MySQL修改資料型別的問題總結
昨天快下班的時候,突然開發的同事找我說有個緊急需求,負責這個業務的DBA同事回家了,想讓我幫忙看看,執行個SQL語句,幾秒鐘就好。我一聽,就本著人道主義的精神留下來處理,但是發現似乎留給我的是一個大坑。
瞭解了問題之後,讓我有些後背發涼,這個表根據開發同事反饋有20億的資料,這得多大的一個表啊,當前的問題是這個表裡的主鍵id資料型別是int,因為資料型別的限制已經達到了最大值,現在插入不了資料了。希望我幫忙處理一下,把資料型別修改為bigint.
我們簡單來了解一下MySQL的資料型別。
對於資料型別有下面的一些總結,更詳細可以參見之前寫的一篇。http://blog.itpub.net/23718752/viewspace-1371434/
所以現在的int資料型別已經達到了最大值2 147 483 647。
修改資料型別,擴充套件一般是可行的,但是這個環境MySQL版本還比較低,所以pt-osc的工具是別想了,而且20億的資料就算處理也得耗上不少的時間。
簡答瞭解了下問題,我一直糾結這個修改資料型別的操作影響時長。
20億的資料做這樣的操作,想必經歷的人也不會太多,偏偏當了友情支援,我登入到指定的環境,仔細一看,這個表原來沒有20億的資料,只是id遞增到了20億的級別,表裡有幾百萬的資料,對應的資料檔案看有500M左右,所以這個問題讓我懸著的心終於踏實了一些。
# ll -h activity_dj_actor_info_log*
-rw-rw---- 1 mysql mysql 8.7K Sep 29 2014 activity_dj_actor_info_log.frm
-rw-rw---- 1 mysql mysql 560M Nov 4 19:05 activity_dj_actor_info_log.ibd
這個修改資料型別的操作持續了大概1分多鐘就結束了。
提供的語句如下:
> ALTER TABLE activity_dj_actor_info_log modify id BIGINT;
Query OK, 3144626 rows affected (1 min 22.64 sec)
Records: 3144626 Duplicates: 0 Warnings: 0
檢視執行緒的情況,可以看到存在這麼一個copy to tmp table的操作,證明在後臺重建表資料。
修改完成之後檢視,發現有個地方不對勁,怎麼沒有了auto_increment的屬性。
> show create table activity_dj_actor_info_log\G
*************************** 1. row ***************************
Table: activity_dj_actor_info_log
Create Table: CREATE TABLE `activity_dj_actor_info_log` (
`id` bigint(20) NOT NULL DEFAULT '0',
`cnMaster` varchar(50) NOT NULL,
。。。
PRIMARY KEY (`id`),
UNIQUE KEY `dss_cnMaster` (`cnMaster`,`serverId`,`guid`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
使用下面的方式修改,讓欄位id遞增,竟然丟擲了錯誤。
> ALTER TABLE activity_dj_actor_info_log modify id BIGINT AUTO_INCREMENT;
ERROR 1062 (23000): ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry '1' for key 'PRIMARY'
就是這個錯誤讓我糾結了半天。
而且稍後繼續嘗試,修改auto_increment的值,竟然沒有反應。
> ALTER TABLE activity_dj_actor_info_log AUTO_INCREMENT=2147483649;
Query OK, 3144627 rows affected (1 min 20.65 sec)
Records: 3144627 Duplicates: 0 Warnings: 0
> show create table activity_dj_actor_info_log\G
*************************** 1. row ***************************
Table: activity_dj_actor_info_log
Create Table: CREATE TABLE `activity_dj_actor_info_log` (
`id` bigint(20) NOT NULL DEFAULT '0',
`cnMaster` varchar(50) NOT NULL,
。。。
PRIMARY KEY (`id`),
UNIQUE KEY `dss_cnMaster` (`cnMaster`,`serverId`,`guid`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8
這問題就很糾結了,修改成功,但是檢視錶定義沒有生效,檢視資料字典裡的遞增序列值還是NULL,證明自增序列沒有生效。
> SELECT AUTO_INCREMENT FROM information_schema.tables WHERE table_name="activity_dj_actor_info_log";
+----------------+
| AUTO_INCREMENT |
+----------------+
| NULL |
+----------------+
2 rows in set (0.00 sec)
在經過幾次嘗試之後,最後是採用下面的方式才修復了這個問題。
> alter table `activity_dj_actor_info_log` change `id` `id` bigint NOT NULL AUTO_INCREMENT , drop primary key,add primary key(id);
ERROR 1062 (23000): ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry '1' for key 'PRIMARY'
> alter table `activity_dj_actor_info_log` drop primary key;
Query OK, 3144627 rows affected (1 min 13.75 sec)
Records: 3144627 Duplicates: 0 Warnings: 0
> alter table `activity_dj_actor_info_log` change `id` `id` bigint NOT NULL AUTO_INCREMENT , add primary key(id);
Query OK, 3144627 rows affected (1 min 32.32 sec)
Records: 3144627 Duplicates: 0 Warnings: 0
> show create table activity_dj_actor_info_log\G
*************************** 1. row ***************************
Table: activity_dj_actor_info_log
Create Table: CREATE TABLE `activity_dj_actor_info_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`cnMaster` varchar(50) NOT NULL,
。。。
PRIMARY KEY (`id`),
UNIQUE KEY `dss_cnMaster` (`cnMaster`,`serverId`,`guid`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=2150192178 DEFAULT CHARSET=utf8
和開發的同事簡單溝通之後,沒過一會檢視就發現數值是遞增了。
> select max(id) from activity_dj_actor_info_log;
+------------+
| max(id) |
+------------+
| 2150195418 |
+------------+
而對於這個問題,自己也簡單總結了下,其實最開始處理的時候就不嚴謹,導致了後面的不斷修復,如果一步到位就不會有這麼多的麻煩了。
所以在本地有簡單測試了下。
CREATE TABLE `activity_dj_actor_info_log` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`cnMaster` varchar(50) NOT NULL,
。。。
PRIMARY KEY (`id`),
UNIQUE KEY `dss_cnMaster` (`cnMaster`,`serverId`,`guid`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=2147483647 DEFAULT CHARSET=utf8;
插入一部分測試資料。
> insert into activity_dj_actor_info_log select *from activity_log.activity_dj_actor_info_log limit 1,1000;
Query OK, 1000 rows affected (0.07 sec)
Records: 1000 Duplicates: 0 Warnings: 0
修改表欄位資料型別
> alter table activity_dj_actor_info_log modify `id` bigint NOT NULL AUTO_INCREMENT;
Query OK, 1000 rows affected (0.43 sec)
Records: 1000 Duplicates: 0 Warnings: 0
再次檢視遞增序列就修改完善了。
> show create table activity_dj_actor_info_log;
| Table | Create Table
| activity_dj_actor_info_log | CREATE TABLE `activity_dj_actor_info_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`cnMaster` varchar(50) NOT NULL,
。。。
PRIMARY KEY (`id`),
UNIQUE KEY `dss_cnMaster` (`cnMaster`,`serverId`,`guid`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=2147483647 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
在這一點上,Oracle的處理和MySQL還是存在一些區別,還是需要嚴格區別對待。
瞭解了問題之後,讓我有些後背發涼,這個表根據開發同事反饋有20億的資料,這得多大的一個表啊,當前的問題是這個表裡的主鍵id資料型別是int,因為資料型別的限制已經達到了最大值,現在插入不了資料了。希望我幫忙處理一下,把資料型別修改為bigint.
我們簡單來了解一下MySQL的資料型別。
對於資料型別有下面的一些總結,更詳細可以參見之前寫的一篇。http://blog.itpub.net/23718752/viewspace-1371434/
型別 | 大小 | 範圍(有符號) | 範圍(無符號) | 用途 |
---|---|---|---|---|
TINYINT | 1 位元組 | (-128,127) | (0,255) | 小整數值 |
SMALLINT | 2 位元組 | (-32 768,32 767) | (0,65 535) | 大整數值 |
MEDIUMINT | 3 位元組 | (-8 388 608,8 388 607) | (0,16 777 215) | 大整數值 |
INT或INTEGER | 4 位元組 | (-2 147 483 648,2 147 483 647) | (0,4 294 967 295) | 大整數值 |
BIGINT | 8 位元組 | (-9 233 372 036 854 775 808,9 223 372 036 854 775 807) | (0,18 446 744 073 709 551 615) |
極大整數值 |
修改資料型別,擴充套件一般是可行的,但是這個環境MySQL版本還比較低,所以pt-osc的工具是別想了,而且20億的資料就算處理也得耗上不少的時間。
簡答瞭解了下問題,我一直糾結這個修改資料型別的操作影響時長。
20億的資料做這樣的操作,想必經歷的人也不會太多,偏偏當了友情支援,我登入到指定的環境,仔細一看,這個表原來沒有20億的資料,只是id遞增到了20億的級別,表裡有幾百萬的資料,對應的資料檔案看有500M左右,所以這個問題讓我懸著的心終於踏實了一些。
# ll -h activity_dj_actor_info_log*
-rw-rw---- 1 mysql mysql 8.7K Sep 29 2014 activity_dj_actor_info_log.frm
-rw-rw---- 1 mysql mysql 560M Nov 4 19:05 activity_dj_actor_info_log.ibd
這個修改資料型別的操作持續了大概1分多鐘就結束了。
提供的語句如下:
> ALTER TABLE activity_dj_actor_info_log modify id BIGINT;
Query OK, 3144626 rows affected (1 min 22.64 sec)
Records: 3144626 Duplicates: 0 Warnings: 0
檢視執行緒的情況,可以看到存在這麼一個copy to tmp table的操作,證明在後臺重建表資料。
修改完成之後檢視,發現有個地方不對勁,怎麼沒有了auto_increment的屬性。
> show create table activity_dj_actor_info_log\G
*************************** 1. row ***************************
Table: activity_dj_actor_info_log
Create Table: CREATE TABLE `activity_dj_actor_info_log` (
`id` bigint(20) NOT NULL DEFAULT '0',
`cnMaster` varchar(50) NOT NULL,
。。。
PRIMARY KEY (`id`),
UNIQUE KEY `dss_cnMaster` (`cnMaster`,`serverId`,`guid`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
使用下面的方式修改,讓欄位id遞增,竟然丟擲了錯誤。
> ALTER TABLE activity_dj_actor_info_log modify id BIGINT AUTO_INCREMENT;
ERROR 1062 (23000): ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry '1' for key 'PRIMARY'
就是這個錯誤讓我糾結了半天。
而且稍後繼續嘗試,修改auto_increment的值,竟然沒有反應。
> ALTER TABLE activity_dj_actor_info_log AUTO_INCREMENT=2147483649;
Query OK, 3144627 rows affected (1 min 20.65 sec)
Records: 3144627 Duplicates: 0 Warnings: 0
> show create table activity_dj_actor_info_log\G
*************************** 1. row ***************************
Table: activity_dj_actor_info_log
Create Table: CREATE TABLE `activity_dj_actor_info_log` (
`id` bigint(20) NOT NULL DEFAULT '0',
`cnMaster` varchar(50) NOT NULL,
。。。
PRIMARY KEY (`id`),
UNIQUE KEY `dss_cnMaster` (`cnMaster`,`serverId`,`guid`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8
這問題就很糾結了,修改成功,但是檢視錶定義沒有生效,檢視資料字典裡的遞增序列值還是NULL,證明自增序列沒有生效。
> SELECT AUTO_INCREMENT FROM information_schema.tables WHERE table_name="activity_dj_actor_info_log";
+----------------+
| AUTO_INCREMENT |
+----------------+
| NULL |
+----------------+
2 rows in set (0.00 sec)
在經過幾次嘗試之後,最後是採用下面的方式才修復了這個問題。
> alter table `activity_dj_actor_info_log` change `id` `id` bigint NOT NULL AUTO_INCREMENT , drop primary key,add primary key(id);
ERROR 1062 (23000): ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry '1' for key 'PRIMARY'
> alter table `activity_dj_actor_info_log` drop primary key;
Query OK, 3144627 rows affected (1 min 13.75 sec)
Records: 3144627 Duplicates: 0 Warnings: 0
> alter table `activity_dj_actor_info_log` change `id` `id` bigint NOT NULL AUTO_INCREMENT , add primary key(id);
Query OK, 3144627 rows affected (1 min 32.32 sec)
Records: 3144627 Duplicates: 0 Warnings: 0
> show create table activity_dj_actor_info_log\G
*************************** 1. row ***************************
Table: activity_dj_actor_info_log
Create Table: CREATE TABLE `activity_dj_actor_info_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`cnMaster` varchar(50) NOT NULL,
。。。
PRIMARY KEY (`id`),
UNIQUE KEY `dss_cnMaster` (`cnMaster`,`serverId`,`guid`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=2150192178 DEFAULT CHARSET=utf8
和開發的同事簡單溝通之後,沒過一會檢視就發現數值是遞增了。
> select max(id) from activity_dj_actor_info_log;
+------------+
| max(id) |
+------------+
| 2150195418 |
+------------+
而對於這個問題,自己也簡單總結了下,其實最開始處理的時候就不嚴謹,導致了後面的不斷修復,如果一步到位就不會有這麼多的麻煩了。
所以在本地有簡單測試了下。
CREATE TABLE `activity_dj_actor_info_log` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`cnMaster` varchar(50) NOT NULL,
。。。
PRIMARY KEY (`id`),
UNIQUE KEY `dss_cnMaster` (`cnMaster`,`serverId`,`guid`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=2147483647 DEFAULT CHARSET=utf8;
插入一部分測試資料。
> insert into activity_dj_actor_info_log select *from activity_log.activity_dj_actor_info_log limit 1,1000;
Query OK, 1000 rows affected (0.07 sec)
Records: 1000 Duplicates: 0 Warnings: 0
修改表欄位資料型別
> alter table activity_dj_actor_info_log modify `id` bigint NOT NULL AUTO_INCREMENT;
Query OK, 1000 rows affected (0.43 sec)
Records: 1000 Duplicates: 0 Warnings: 0
再次檢視遞增序列就修改完善了。
> show create table activity_dj_actor_info_log;
| Table | Create Table
| activity_dj_actor_info_log | CREATE TABLE `activity_dj_actor_info_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`cnMaster` varchar(50) NOT NULL,
。。。
PRIMARY KEY (`id`),
UNIQUE KEY `dss_cnMaster` (`cnMaster`,`serverId`,`guid`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=2147483647 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
在這一點上,Oracle的處理和MySQL還是存在一些區別,還是需要嚴格區別對待。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23718752/viewspace-2127869/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Mysql支援的資料型別(總結)MySql資料型別
- (2)mysql 支援的資料型別總結MySql資料型別
- MySQL的主鍵和欄位型別問題總結MySql型別
- MySQL與oracle的資料型別轉換總結MySqlOracle資料型別
- 修改MySQL資料型別報 Changing columns for table XXX 錯的問題MySql資料型別
- Go 的資料型別總結Go資料型別
- JS 資料型別總結JS資料型別
- mysql資料型別小結MySql資料型別
- PHP弱型別安全問題總結PHP型別
- Python的資料型別總結Python資料型別
- go 基礎總結 --- 資料型別Go資料型別
- JavaScript資料型別轉換總結JavaScript資料型別
- C++基本資料型別總結C++資料型別
- MySQL 的資料型別MySql資料型別
- MySQL的資料型別MySql資料型別
- MSSQL資料庫的欄位型別總結SQL資料庫型別
- 可變資料型別(mutable)與不可變資料型別(immutable)總結資料型別
- CDM修改資料型別的方法資料型別
- MYSQL 資料型別MySQL 資料型別
- [Mysql]資料型別MySql資料型別
- MySQL資料型別MySql資料型別
- JS基礎總結(1)——資料型別JS資料型別
- MySQL 5 不允許TEXT資料型別的列有預設值的問題!MySql資料型別
- mysql 常用的資料型別MySql資料型別
- C++的資料型別總結,不能錯過C++資料型別
- 修改欄位資料型別的方法資料型別
- MySQL資料庫中修改密碼方法總結(轉)MySql資料庫密碼
- mysql常見問題總結MySql
- mysql相關問題總結MySql
- 理解MySQL資料型別MySql資料型別
- MySQL基本資料型別MySql資料型別
- Python3學習(基本資料型別-集合-字典-基本資料型別總結)Python資料型別
- long資料型別跨平臺問題資料型別
- 關於修改分割槽表的問題總結
- Mysql 資料型別之整數型別MySQL 資料型別
- 【MySQL資料型別3之--字元型別】MySql資料型別字元
- 使用Oracle資料泵問題總結Oracle
- 資料遷移部分問題總結