升級 MySQL
1、概述
通常,從一個發布版本升級到另一個版本時,我們建議按照順序來升級版本。例如,想要升級 MySQL 3.23 時,先升級到 MySQL 4.0,而不是直接升級到 MySQL 4.1 或 MySQL 5.0。
以下是在升級 MySQL 時需要注意的事項:
- 仔細閱讀一下升級的目標版本的新特性和改變的特性,以及2個版本之間的不同特性
- 升級前一定要備份所有的數據
- 如果是在Windows平臺上升級MySQL,請閱讀附錄"在Windows平臺上升級MySQL"
- 有些不同版本間的升級可能會涉及對授權表的修改,請尤其注意這個問題,詳情請閱讀附錄"升級授權表"
- 如果正在運行著同步,請閱讀附錄"升級同步"
- 如果之前運行著MySQL-Max發布版本,想要升級到非MySQL-Max發布版本時,就需要從 mysqld_safe 去掉啟動 mysqld-max服務器的參數
在同一個發布系列版本的MySQL間,可以隨意拷貝格式文件和數據文件。如果在MySQL運行過程中改變了字符集,就需要對每個MyISAM表執行"myisamchk -r -q --set-character-set=charset
"命令修復一下。否則的話,索引的排序可能不正確,因為修改了字符集,就可能會改變索引的順序。
通常情況下,升級到新版本不需要修改任何數據表。請檢查MySQL發布事項中提到的升級需要注意的地方,如果發現不能直接升級的話,就先用 mysqldump 將數據導出來,然后再導回去。
如果擔心升級失敗,就先把舊版本的MySQL改個名字備份起來,以備所需。
同時,升級完之后可能還需要重新編譯跟MySQL相關的程序,因為新版本的頭文件和庫文件可能有改變了。
如果升級后發生問題了,請先檢查是否使用了舊的my.cnf配置文件,可以通過執行命令"mysqld --print-defaults"來打印出各種配置信息來確認。
升級的時候最好也升級類似Perl的 DBD::mysql 模塊,同樣,對PHP和Python而言也是一樣。
2、從 MySQL 5.0 升級到 MySQL 5.1
從 5.0 升級到 5.1 的時候,必須要升級授權表。否則,可能某些存儲過程無法運行。詳情請看附錄"mysql_update
MySQL升級時檢查數據表"。
以下是從 5.0 升級到 5.1 需要注意的事項:
- 檢查所有的變化,尤其注意那些標志為"不兼容的變化"的部分。詳情請看附錄"
mysql_update
MySQL升級時檢查數據表" - 可能某些發布版本會改變授權表的機制
- 查看所有重大的變化,詳情請看MySQL手冊的"D.1.1.?Changes in release 5.1.10 (Not yet released)"章節
以下是升級到MySQL 5.1之后會發生的一些變化:
服務器部分:
-
不兼容的變化:MySQL 5.1 實現了支持無需重啟服務器就能在運行時加載或卸載API插件。這個特性需要用到mysql.plugin表,可以運行"mysql_upgrade"命令來創建該表
插件安裝在系統變量
plugin_dir
所指的目錄下。這個變量也控制著用戶自定義函數(UDFs)所在目錄,這相對以前的版本有所改變。在MySQL 5.1中,所有的UDFs庫必須都安裝到plugin_dir
目錄下,從舊版本升級的時候,必須把那些庫文件都移動到這個目錄下 - 不兼容的變化:系統變量
table_cache
改名為table_open_cache
- 不兼容的變化:在MySQL 5.1.6 中 FULLTEXT 的索引結構發生變化了。當升級到 5.1.6 甚至更高之后,需要對每個包含 FULLTEXT 字段的數據表執行"REPAIR TABLE"語句
- 在 MySQL 5.1.6 以前,MySQL把普通的查詢日志和慢查詢都寫到文件中。從5.1.6以后,這些日志可以靈活地選擇是是寫到日志文件中(跟以前一樣)或者寫到
mysql
數據庫的general_log
和slow_log
表中。如果啟用日志記錄,這2種方式都可以使用。選項--log-output
用來控制這2種日志的記錄方式 - 從5.1.6開始,特殊字符集的數據庫和表的標識符在創建相應目錄和文件時都會用對應的字符集編碼了
SQL分:
- 不兼容的變化:在MySQL 5.1.8開始,
TYPE =
還仍然是engine_name
ENGINE =
的同義語法,但有警告。從5.2開始,將完全刪除這種語法,并報告錯誤。engine_name
- 不兼容的變化:在MySQL 5.0.10中,觸發器的命名空間已經改變了。在以前,觸發器的名字必須和每個數據表都不一樣。現在,只需要在數據庫內唯一就行了。隱含的變化就是,
DROP TRIGGER
語法使用模式名而非數據表名(模式名是可選參數,如果忽略了,就使用當前的模式)當從5.0升級到5.0.10及更高時,則必須刪除觸發器后重新創建它們,否則升級后就無法刪除觸發器了。建議如下:
- 導出觸發器:
SELECT CONCAT('CREATE TRIGGER ', t.TRIGGER_SCHEMA, '.', t.TRIGGER_NAME,
' ', t.ACTION_TIMING, ' ', t.EVENT_MANIPULATION, ' ON ',
t.EVENT_OBJECT_SCHEMA, '.', t.EVENT_OBJECT_TABLE,
' FOR EACH ROW ', t.ACTION_STATEMENT, '//' )
INTO OUTFILE '/tmp/triggers.sql'
FROM INFORMATION_SCHEMA.TRIGGERS AS t; - 停止服務器,然后刪除數據庫目錄下的所有"TRG"文件:
shell>rm -f */*.TRG
- 啟動服務器,倒入觸發器:
mysql> delimiter // ;
mysql> source /tmp/triggers.sql //
- 導出觸發器:
- 不兼容的變化:MySQL 5.1.6引進了觸發器權限機制。以前,創建觸發器需要有
SUPER
權限,現在,這個操作只需要有TRIGGER
權限。這改善了權限安全狀況 - 一些MySQL 5.1中作為保留關鍵字在MySQL 5.0中并沒有作為保留關鍵字
- 新引入了"
INSTALL PLUGIN
"和"UNINSTALL PLUGIN
"語句用于操作API插件。同樣,創建FULLTEXT
索引時,可以用"WITH PARSER
"子句關聯解析器插件
3、從 MySQL 4.1 升級到 MySQL 5.0
服務器部分:
- 不兼容的變化:
InnoDB
和MyISAM
表中空格結尾的TEXT
字段索引順序改變了。因此需要運行"CHECK TABLE
"語句修復數據表,如果出現錯誤,就運行"OPTIMIZE TABLE
"或"REPAIR TABLE
"語句修復,甚至重新轉儲(用mysqldump) - 不兼容的變化:從MySQL 5.0.15開始,如何處理
BINARY
字段中填充的值已經改變了。填充的值現在是0x00
而非空格了,并且在取值的時候不會去除末尾的空格 - 不兼容的變化:從MySQL 5.0.3開始,
DECIMAL
的實現方式已經改變了,5.0對DECIMAL
的格式限制嚴格多了 - 不兼容的變化:在MySQL 5.0.3到5.0.5之間版本的
MyISAM
和InnoDB
表中創建的DECIMAL
字段升級到5.0.6之后會發生崩潰 - 不兼容的變化:從5.0.3開始,除非和主函數之間有輔助的符號鏈接,否則服務器將不再默認地加載用戶自定義函數(UDFs),也可以通過
--allow-suspicious-udfs
選項來啟用 - 不兼容的變化:5.0中禁用了更新日志(update log),不過可以用二進制日志(binary log)來代替它
- 不兼容的變化:5.0中不再支持
ISAM
類型存儲引擎(作者:可以通過重新編譯源代碼支持,不過非常不建議這么做) - 不兼容的變化:5.0中不再支持
MyISAM
的RAID
選項,可以用 mysqldump 導出舊表然后重新導回去實現升級 - 在5.0.6中,記錄存儲過程和觸發器的二進制日志發生了一些變化,詳見手冊的"17.4 Binary Logging of Stored Routines and Triggers"
SQL部分:
- 不兼容的變化:從5.0.12開始,自然連接和使用
USING
的連接,包括外部連接的衍生形式,都按照SQL:2003標準來處理了;這個變化導致減少了自然連接和使用USING
的連接產生的結果字段數,并且還將按照更合理的順序顯示這些字段,逗號比較符的優先順序和JOIN
,LEFT JOIN
中的一樣了 - 不兼容的變化:在以前,等待超時的鎖會導致
InnoDB
回滾當前全部事務,從5.0.13開始,就只回滾最近的SQL語句了 - 不兼容的變化:觸發器的變化,跟前面講到的一樣
- 不兼容的變化:從5.0.15開始,
CHAR()
函數返回二進制字符串,而不是按照連接字符集格式的字符串。子句USING
可以自定義返回結果的字符集charset_name
- 不兼容的變化:在5.0.13以前,
NOW()
和SYSDATE()
返回的結果一樣。但從5.0.13開始,SYSDATE()
返回的是語句執行點的時間,這就可能和NOW()
返回的結果不一樣了,不過可以用--sysdate-is-now
選項讓SYSDATE()
作為NOW()
的同名函數 - 不兼容的變化:在5.0.13以前,
GREATEST(
和x
,NULL)LEAST(
如果x
,NULL)x
不是NULL
值,則返回x
。從5.0.13開始,只要任何參數是NULL
,就返回NULL,跟Oracle一樣
- 不兼容的變化:在4.1.13/5.0.8以前,
DATETIME
的加0后就轉換成YYYYMMDDHHMMSS
格式,現在變成YYYYMMDDHHMMSS.000000
格式了 - 不兼容的變化:在4.1.12/5.0.6中,語句
LOAD DATA INFILE
和SELECT ... INTO OUTFILE 中,
當FIELDS TERMINATED BY
和FIELDS ENCLOSED BY
的值都是空的時候,結果就被改變了。以前,字段都按照它顯示的寬度來讀寫的。現在變成按照足夠保存字段值的寬度來讀寫它。然而,對MySQL 4.0.12/5.0.6來說,那些在它們之前導出來的文件可能無法正確用LOAD DATA INFILE
語句導入 - 一些MySQL 5.0中作為保留關鍵字在MySQL 4.1中并沒有作為保留關鍵字
- 從5.0.3開始,
DECIMAL
用更有效的格式來存儲 - 5.0.3開始,在計算
DECIMAL
值和舍入精確值的時候采用精確數學 - 4.1中,
FLOAT
或DOUBLE
之間的比較碰巧沒問題,但在5.0中可能就不行了 - 從5.0.3開始,
VARCHAR
和VARBINARY
字段中末尾的空格不再刪除 - 從5.0.3開始,
BIT
是一個獨立的數據類型了,不再是TINYINT(1)
的同名詞了 - MySQL 5.0.2增加了一些SQL模式以使對排除包含非法或者缺失值得記錄有著更嚴格的控制
- 從5.0.2開始,關鍵字
SCHEMA
和SCHEMAS
被認為分別是DATABASE
和DATABASES
的同名詞 - 5.0中用戶變量對大小寫不敏感,而4.1中則不然
- 增加了一個新的啟動選項
innodb_table_locks
,它導致LOCK TABLE
時也可以請求InnoDB
表鎖。這個選項默認打開,不過可能在AUTOCOMMIT=1
和LOCK TABLES
應用中會導致死鎖
C API部分:
- 不兼容的變化:由于5.0中
DECIMAL
數據類型的實現方式發生了變化,因此如果使用就版本的庫文件需要注意這個問題 - 不兼容的變化:
在5.0.3中,ER_WARN_DATA_TRUNCATED
警告符號改名為WARN_DATA_TRUNCATED
了 MYSQL
結構體中的reconnect
標志被mysql_real_connect()
設為 0。
4、從 MySQL 4.0 升級到 MySQL 4.1
服務器部分:
-
不兼容的變化:以下好幾個都是需要重建數據表的,可以使用 mysqldump 導出表后重新導回去
- 如果在4.1.0到4.1.3版本的MySQL中創建了包含
TIMESTAMP
字段的InnoDB
表。則在升級到4.1.4及更高時需要重建表,因為存儲格式發生變化了 - 從4.1.3開始,
InnoDB
表采用同一種字符集比較函數來比較那些非latin1_swedish_ci
字符集且不是BINARY
的字符串 - 如果在4.1.0到4.1.5版本的MySQl中對 UTF8 字段或者其他多字節字段作了前綴索引,則在升級到4.1.6及更高時必須重建表
- 如果在4.1之前,數據庫、表、字段、約束名中使用了重音字符(字節值是128到255的字符),那么不能直接升級到4.1。因為4.1使用 UTF8 來存儲元數據名。
- 字符串根據標準SQL來比較:比較之前不刪除末尾的空格,以前用末尾空格擴展了比較短的字符串。現在的結果是
'a'> 'a\t'
,以前則不這樣。可以用 mysqlcheck來檢查一下數據表 MyISAM
現在使用更好的校驗和算法了
- 如果在4.1.0到4.1.3版本的MySQL中創建了包含
- 不兼容的變化:MySQL把字符串類型字段的長度定義理解為字符長度而不是字節長度。
- 重要提示:MySQL 4.1用
UTF8
字符集存儲數據表名和字段名。如果有用標準 7字節 US-ASCII 范圍之外的字符作為表名/字段名的話,需要重建表 - 重要提示:升級到4.1.1或更高后,就很難降級回到4.0或4.1了,因為
InnoDB
使用了多個表空間的緣故 - 不兼容的變化:MySQL 4.1.13支持讓每個連接設定時區,因此系統變量
timezone
改成system_time_zone
所有的數據表和非二進制字符串(
CHAR
,VARCHAR
,和TEXT
)的字段都有字符集
,二進制字符串字段包括BINARY
,VARBINARY
,和BLOB
MySQL4.0中,如果有字段類型為
CHAR BINARY
或VARCHAR BINARY
,則它們會被當作二進制字符串類型- 如果數據表的字段中存儲著MySQL 4.1直接就能支持的字符集字符數據時,則可以將這個字段的值轉換成由合適的字符集存儲
- MySQL 4.1中對數據結構描述文件
.frm
的格式稍作改進,新版本能兼容這個新格式,但是舊版本則不能 - windows下的服務器啟動時增加
--shared-memory
選項即可支持從本地客戶端連接時使用共享內存 - 不兼容的變化:從MySQL 4.1.1開始,對用戶自定義函數集合接口發生了很大改進
- 不兼容的變化:從4.1.10a開始,除非和主函數之間有輔助的鏈接,否則服務器將不再默認地加載用戶自定義函數(UDFs),也可以通過
--allow-suspicious-udfs
選項來啟用
客戶端部分:
- mysqldump 默認啟用
--opt
和--quote-names
選項
SQL部分:
- 不兼容的變化:字符串根據標準SQL來比較,如上面的"服務器變化"部分中提到的
- 不兼容的變化:
TIMESTAMP
返回'YYYY-MM-DD HH:MM:SS'
格式的字符串。在MySQL 4.0中,可以增加選項--new
來獲得MySQL 4.1中這方面的特性 - 不兼容的變化:二進制數據例如
0xFFDF
被當成字符串而非數字 - 不兼容的變化:在MySQL 4.1.1前,語句解析器不是那么嚴格,它在處理字符串轉時間轉換時會忽略第一個數字前的其他字符。在4.1.1之后,就比較嚴格了
- 不兼容的變化:在MySQL 4.1.2,
SHOW TABLE STATUS
結果的Type
字段改名為Engine
了 - 當執行多表刪除語句時,要刪除的表只能使用它的別名,而不能用真實表名
- 返回結果是
DATE
,DATETIME
,或TIME
類型的函數的結果會被轉換成時間型 AUTO_INCREMENT
字段不能設定默認(DEFAULT)
值了LIMIT
不再接受負數參數了SERIALIZE
不再是sql_mode
變量的有效值了,它的取代值是SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
C API部分:
MySQL 4.1中的密碼哈希算法做了改進以提升安全性,不過會導致兼容性問題。使用MySQL 4.0及更早版本的客戶端庫文件會發生問題。
- 不兼容的變化:
mysql_shutdown()
函數增加一個參數:SHUTDOWN
-level - 某些函數例如
mysql_real_query()
發生錯誤時返回1
而非-1
密碼處理部分:
MySQL 4.1中的密碼哈希算法做了改進以提升安全性,不過會導致兼容性問題。使用MySQL 4.0及更早版本的客戶端庫文件會發生問題。解決辦法有:
- 升級客戶端庫文件到4.1(不用升級服務器端庫文件)
- 運行 mysql_fix_privilege_tables 腳本來加寬 user 表中的 Password 字段值,以適應新的哈希算法。如果想要允許4.1以下的客戶端還能連接到服務器,那么服務器運行時要增加參數--old-passwords
5、附錄
在Windows平臺上升級MySQL步驟:
- 備份舊數據
- 停止舊服務器
- 從windows的系統服務中刪掉mysql服務,用如下命令:
C:\> C:\mysql\bin\mysqld --remove
- 用可執行安裝文件方式安裝mysql,或者解壓可直接執行的二進制壓縮包來安裝
- 重新注冊mysql服務,用如下命令:
C:\> C:\mysql\bin\mysqld --install
- 重啟服務器
- 其他的問題詳見上面提到的各種升級中會碰到的情況
2、)升級授權表
升級授權表之前一定要備份好 mysql
數據庫,以備升級失敗時使用舊的授權表。
在unix或類unix系統中,運行 mysql_fix_privilege_tables 腳本來升級授權表:
必須在 mysqld
運行著的時候執行這個腳本,它嘗試使用 root 帳號來連接服務器;因此,當 root 需要密碼時,用如下方式來指定密碼:
在 MySQL 4.1之前,則是用如下形式來指定密碼:
接下來 mysql_fix_privilege_tables
腳本會升級授權表,在這個過程中可能會有一些 Duplicate column name
警告信息,無需理會它們。待它運行完之后,重啟一下服務器即可。
在windows平臺上,授權表想要升級到4.0.15并不容易。從4.0.15開始,發行版中包含一個sql腳本:mysql_fix_privilege_tables.sql
,用 mysql 客戶端運行它來升級授權表,運行類似如下命令:
mysql> SOURCE C:/mysql/scripts/mysql_fix_privilege_tables.sql
把上面提到的目錄改成真實的目錄。
3、)升級同步
請查看我翻譯的文檔"6.6 升級同步"
4、) mysql_update
MySQL升級時檢查數據表
每次升級的時候都必須運行 mysql_upgrade 腳本。它檢查了當前版本的MySQL下的所有數據庫表的不兼容性,就會檢查這些表;并且發現有問題時,也會修復這些表。mysql_update
同時升級了系統表,因此可以兼容新的權限機制并且使用新增的權限。
由于 mysql_update
會把檢查過和修復過的表都標記上當前的MySQL版本號,因而保證了下一次在同一個MySQL版本下運行這個腳本時,都會再次報告哪些表需要修復或檢查。
它還會把MySQL的版本號記錄在數據文件目錄下的一個文件中:mysql_upgrade.info
。這個文件用于標識當前發布版本檢查表時哪些表可以略過,檢查時想要忽略這個文件,只需附加上 --force
選項。
為了能檢查和修復數據表,并且升級系統表,mysql_update
執行了一下命令:
mysql_fix_privilege_tables
mysql_update
目前只支持類unix平臺;在windows下,需要手工執行 mysqlcheck 命令,升級授權表請看附錄"升級授權表"。
執行 mysql_update
時,MySQL服務器必須運行著,它有以下幾個參數:
--help
顯示幫助信息并且退出
--basedir=
path
設定MySQL的安裝路徑
--datadir=
path
設定MySQL的數據文件路徑
--force
告訴
mysql_update
,在檢查時忽略是否存在mysql_upgrade.info
文件,強行檢查該版本的MySQL數據表,不管是否已經檢查過了--user=
,user_name
-u
user_name
連接到MySQL的用戶名,默認是
root
--verbose
冗余模式。發生問題時打印出更多的信息
其他的選項諸如 --password[=
是要傳遞給 mysqlcheck 和 mysql_fix_privilege_tables 腳本的,并不是必須的。password
]