全部產品
Search
文件中心

PolarDB:大版本升級最佳實務

更新時間:Jul 06, 2024

本文介紹PolarDB MySQL版的5.6、5.7版本和MySQL 5.6、5.7版本升級至PolarDB MySQL版的8.0版本的優勢、預檢查以及相容性說明等內容。

PolarDB MySQL版8.0版本概述

  • 版本發布日期

    • 8.0.1版本發佈於2019年12月3日。

    • 8.0.2版本發佈於2020年7月22日。

  • 版本優勢

    8.0版本增強了架構和核心能力,為使用者處理業務提供了更靈活的技術解決方案,效能提升明顯。詳情請參見功能特性

相容性預檢查

PolarDB MySQL版的5.6、5.7版本和MySQL 5.6、5.7版本向的8.0版本升級過程中,經常會遇到效能、文法相容以及周邊組件是否支援的問題。查詢的效能問題一般是由於最佳化器升級導致執行計畫有變化,此類問題需要對效能低下的語句進行針對性的效能最佳化,單獨的效能問題基本不會引發業務報錯以及代碼改寫的問題,此類問題不在本文討論範圍之內。

本文主要討論相容性問題,此類問題需要在資料庫升級過程中,更新相應的代碼或更改環境配置,引發此類問題的主要原因為版本升級後部分文法的變化以及特性的更新和移除。如果確保上述內容不存在問題,可以跳過下面章節進行升級,詳情請參見大版本一鍵升級

預檢查功能會提供一個簡要清單,協助您在升級前更好地瞭解升級過程中可能需要注意的問題。如果下述內容存在對應的問題,請參考後續內容進行操作和檢查。

  • 確保沒有使用廢棄的資料類型、函數和功能,廢棄清單資訊請參見Features Removed in MySQL 8.0

  • 確保觸發器(Triggers)沒有丟失、空的definer或無效的內容。

  • 確保只有InnoDB引擎的分區表。

  • 確保關鍵字和保留關鍵字沒有衝突,詳情請參見Keywords and Reserved Words

  • 確保沒有和MySQL 5.6、5.7版本的系統資料庫、MySQL 8.0版本新增的INNODB_開頭的詞典表名衝突。

  • 確保不依賴於INFORMATION_SCHEMA下的GLOBALLOCALVARIABLESSTATUS表。

  • 確保sql_mode中沒有使用廢棄的變數設定,詳情請參見參數相容性

  • 確保表和預存程序單個ENUMSET列元素的長度不超過255個字元或1020個位元組。

  • 確保表的分區不在共用InnoDB tablespaces資料表空間中。

  • 確保查詢SQL語句中的GROUP BY子句不帶有ASC或DESC。

    說明

    8.0.2.2.11.1版本及以上的版本,在控制台上將loose_group_by_compatible_sorting參數的值設定為TRUE後可以開啟相容模式,相容模式支援在SQL語句中使用帶有ASC或DESC的GROUP BY子句。在控制台上設定參數值的操作步驟請參見設定叢集參數和節點參數

  • 確保外鍵約束名稱不超過64個字元。

說明
  • 為了增強Unicode的支援,推薦您將使用utf8mb3(已廢棄)或utf8(utf8mb3字元集的別名)字元集的對象更改為utf8mb4字元集。更多資訊請參見The utf8mb3 Character Set (3-Byte UTF-8 Unicode Encoding)

  • 升級前需要進行備份,以避免升級過程中可能遇到的其他問題。

引擎和分區表相容性

在8.0版本中,建立MyISAM類型的分區將導致使用沒有此類型支援的儲存引擎的分區表建立語句失敗並出現錯誤(ER_CHECK_NOT_IMPLEMENTED)。有關將表從MyISAM轉換至InnoDB引擎,請參見將表從MyISAM轉換為InnoDB

儲存引擎現支援分區處理常式,且伺服器不再支援通用引擎分區。

InnoDB還提供僅8.0版本支援的本機分區處理常式的儲存引擎。您需要在升級伺服器前,將其他儲存引擎的分區表的儲存引擎轉換為InnoDB儲存引擎,或刪除對應分區表,否則後續將無法使用。如有類似分區,請您提前轉換引擎後再進行升級。檢查引擎文法如下:

SELECT TABLE_SCHEMA, TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE ENGINE NOT IN ('innodb','ndbcluster') AND CREATE_OPTIONS LIKE '%partitioned';

或:

SELECT DISTINCT NAME,SPACE,SPACE_TYPE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES
WHERE NAME LIKE '%#P#%' AND SPACE_TYPE NOT LIKE 'Single';

將引擎更改為InnoDB引擎文法如下:

ALTER TABLE part ENGINE = INNODB;
Query OK, 0 rows affected (0.09 sec)

刪除對應分區表文法如下:

ALTER TABLE part REMOVE PARTITIONING;
Query OK, 0 raws affected (0.06 sec)

如果使用MySQLdump從MySQL 5.6、5.7版本伺服器建立的轉儲檔案中將資料匯入至 8.0版本的伺服器,需確保建立分區表的任何語句都沒有同時指定不被支援的儲存引擎,您可以通過刪除對分區的全部引用、將儲存引擎指定為InnoDB或允許將參數default_storage_engine = InnoDB設定為InnoDB的預設值的方法實現該要求。識別在升級到MySQL 8.0版本之前必須更改的分區表的方法請參見為升級準備安裝。有關分區限制詳細資料請參見與儲存有關的分區限制

字元集和定序相容性

MySQL 8.0版本的預設字元集為utf8mb4。 MySQL 8.0版本和PolarDB MySQL版character_set_server值均預設為utf8,您可以根據業務需求進行調整。為支援Unicode,推薦您將使用的utf8mb3字元集轉換為使用utf8mb4字元集。詳細資料請參見utf8mb3字元集

MySQL 8.0版本新增default_collation_for_utf8mb4參數,該參數的作用為當字元集為utf8mb4時,根據預設定序排序,該參數的預設值為utf8mb3_0900_ai_ci,且該預設值只是MySQL中replication使用的內部參數。

若您在從低版本同步到高版本的過程中沒有遇到lllegal mix of collations的錯誤,不建議您將該預設值修改為utf8mb4_general_ciutf8mb4_0900_ai_ci

  • utf8mb4_0900_ai_ci:基於官方Unicode的規則做通用的排序和比較,準確度高,但比對速度稍慢。

  • utf8mb4_general_ci:精簡集合的定序,目的是提供簡化的設計來加快比對速度,雖然沒有遵循Unicode的規則,但在相同情況下結果符合預期。

定序和字元集不同,它只和排序有關,其中ai表示口音不敏感,即排序時e,è,é,ê和ë之間沒有區別;ci表示不區分大小寫,即排序時p和P之間沒有區別。

說明
  • 在8.0版本向低版本反向同步或dump同步時,可能會存在相容性問題。

  • 在DTS低版本與高版本雙向同步情境下容易出現異常,您需要使用MySQL 5.6、5.7和PolarDB MySQL版5.6、5.7版本預設的排序字元集,否則DTS反向同步的時候會出現異常。

  • 由於定序問題,建立視圖時可能會報錯lllegal mix of collations,例如當您使用了convert(a.c1 using utf8mb4)=b.c1時,可能會報上述錯誤。

  • 當您使用convert(exp using utf8mb4)且不指定collation時,MySQL會按照utf8mb4查詢,返回的charset number值為255。255對應的collation即為MySQL 8.0版本預設的utf8mb4_0900_ai_ci

  • 修改default_collation_for_utf8mb4或在DDL中指定列名、表名或資料庫名時,collation都不會起作用。如果您需要使用convert函數,需要在語句中加入collation,如(convert(a.c1 using utf8mb4)collate utf8mb4_general_ci)=b.c1

  • 修改default_collation_for_utf8mb4參數的預設值,如將預設值修改為utf8mb4_general_ci,會導致出現如下問題:

    • 無法正確讀取SYS庫及其相關函數,報錯lllegal mix of collations(utf8mb4_0900_ai_ci.IMPLICIT) and (utf8mb4_general_ci.IMPLICIT) for operation'='

    • 從8.0.1版本升級到8.0.2時,升級失敗。該參數是8.0版本新增加的參數,建議不要修改該參數,如果必須使用其他值,請在執行升級操作前,前往配額中心,在配額名稱為default_collation_for_utf8mb4操作列,單擊申請,申請將參數的預設值重設為utf8mb4_0900_ai_ci,升級完成後,需要將預設值再修改為utf8mb4_general_ci

參數相容性

lower_case_table_names

從MySQL 8.0.11版本開始,禁止lower_case_table_names使用與伺服器初始化時不同的設定來啟動伺服器。各種資料字典、表欄位使用的定序基於lower_case_table_names伺服器初始化時定義的設定,使用不同的設定重新啟動伺服器時,會導致標識符的排序和比較方式引入不一致。在PolarDB MySQL版 8.0版本中,叢集區分大小寫無法在初始化完成後再次更改,您需要在購買 8.0版本的叢集時選定叢集是否區分大小寫。關於lower_case_table_names參數詳情請參見lower_case_table_names

sql_mode

為避免8.0版本的叢集啟動失敗,請通過NO_AUTO_CREATE_USER從MySQL選項檔案的系統變數sql_mode設定中刪除所有叢集。

您的系統變數設定中不得定義過時的SQL模式,否則sql_mode會引起許多不同的行為,在版本升級時需要確認對齊。需要取消的配置項如下:

DB2, MAXDB, MSSDL, MYSQL323, MYSQL40, ORACLE, POSTGRESQL, NO_FIELD_OPTIONS, NO_KEY_OPTI
說明

以上配置項大多為組合配置,需要注意是否有不一致的mode選項。例如:

  • sql_mode=TRADITIONAL等於配置如下項:

    STRICT_TRANS_TABLES, STRICT_ALL_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISIC
  • 在MySQL5.6、5.7和 5.6、5.7版本預設配置時,sql_mode=TRADITIONAL等於配置如下項:

    STRICT_TRANS_TABLES, STRICT_ALL_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE,
    ERROR_FOR_DIVISIC_BY_ZERO, NO_AUTO_CREATE_USER, and NO_ENGINE_SUBSTITUTION

對比上述配置項,可以看到5.6、5.7版本中多了NO_AUTO_CREATE_USER選項,在8.0版本已經禁止GRANT語句隱式建立帳號,5.6、5.7版本雖然添加了NO_AUTO_CREATE_USER選項,但在指定identified by時,可以使用GRANT建立帳號。

如果您發現啟用ONLY_FULL_GROUP_BY導致現有應⽤程式查詢被拒絕,可以使用以下方法恢複操作:

  • 如果可以修改有問題的查詢,請去除select投影列、HAVING條件或ORDER BY列表中的非聚集列,這些列既不在GROUP BY中,也不與GROUP BY列有任何函數關係。或者您可以使用ANY_VALUE()函數。

  • 如果無法修改有問題的查詢(例如它是由第三方應用程式產生的),請將伺服器啟動時的系統變數sql_mode設定為not enable ONLY_FULL_GROUP_BY

    例如,當描述不是GROUP BY的一部分,且沒有應用彙總函式(例如MINMAX)時,會出現如下情況:

    5.6版本:

    SELECT id, invoice_id, description FROM invoice_line_items GROUP BY invoice_id;
    +----+------------+-------------+
    | id | invoice_id | description |
    +----+------------+-------------+
    | 1 | 1 | New socks |
    | 3 | 2 | Shoes |
    | 5 | 3 | Tie |
    +----+------------+-------------+
    3 rows in set (0.00 sec)

    8.0版本:

    SELECT id, invoice_id, description FROM invoice_line_items GROUP BY invoice_id;
    ERROR 1055 (42000): Expression #3 of SELECT list is not in GROUP BY clause and contains

explicit_defaults_for_timestamp

從MySQL 8.0開始,MySQL官方將explicit_defaults_for_timestamp的預設值從OFF修改成ON。目前PolarDB MySQL版 8.0中該參數的預設值仍然遵循5.6和5.7版本為OFF

如果遷移過程中不希望自動添加NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,則需要將該參數設定成ON

explicit_defaults_for_timestampOFF,MySQL對於TIMESTAMP類型使用了非標準行為:

  • TIMESTAMP類型的列,如果沒有顯性定義NULL屬性,將會自動添加NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP。如果顯性定義NULL屬性,則保留該屬性。

mysql> set explicit_defaults_for_timestamp = OFF;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> create table t1(c1 timestamp);
Query OK, 0 rows affected (0.01 sec)

mysql> show create table t1;
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t1 | CREATE TABLE `t1` (
 `c1` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> drop table t1;
Query OK, 0 rows affected (0.01 sec)

mysql> create table t1(c1 int, c2 timestamp null);
Query OK, 0 rows affected (0.01 sec)

mysql> show create table t1;
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------+
| t1 | CREATE TABLE `t1` (
 `c1` int(11) DEFAULT NULL,
 `c2` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
  • 表中第一個定義TIMESTAMP的列,要麼顯性指定NULL,要麼顯性指定DEFAULT或者ON UPDATE屬性,或者自動增加DEFAULT CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMP屬性。

  • 表中第二個定義TIMESTAMP的列,如果sql_mode沒有設定成NO_ZERO_DATE,且沒有顯性指定NULL或者DEFAULT屬性,會自動定義成DEFAULT '0000-00-00 00:00:00'

    mysql> set sql_mode = '';
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> create table t1(c1 timestamp, c2 timestamp);
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> show create table t1;
    +-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Table | Create Table |
    +-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | t1 | CREATE TABLE `t1` (
     `c1` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
     `c2` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
    +-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.00 sec)

    如果設定成strict 模式的NO_ZERO_DATE,則會報錯:

    mysql> create table t1(c1 timestamp, c2 timestamp);
    ERROR 1067 (42000): Invalid default value for 'c2'
    mysql> create table t1(c1 timestamp, c2 timestamp);

explicit_defaults_for_timestampON時,該非標準行為將會廢棄,該類型和其他類型的行為一致。

視圖/表/關鍵字相容性

InnoDB相關視圖相容

INFORMATION_SCHEMA中基於InnoDB系統資料表的視圖被資料字典表的內部系統檢視表所取代。影響InnoDB INFORMATION_SCHEMA的視圖已重新命名,在系統應用中直接存取InnoDB相關視圖時,需要確認應用中是否已經修改。關於參數INFORMATION_SCHEMA的詳細資料請參見NFORMATION_SCHEMA Tables

重新命名的InnoDB提示模式視圖

舊名稱

新名稱

INNODB_SYS_COLUMNS

INNODB_COLUMNS

INNODB_SYS_DATAFILES

INNODB_DATAFILES

INNODB_SYS_FIELDS

INNODB_FIELDS

INNODB_SYS_FOREIGN

INNODB_FOREIGN

INNODB_SYS_FOREIGN_COLS

INNODB_FOREIGN_COLS

INNODB_SYS_INDEXES

INNODB_INDEXES

INNODB_SYS_TABLES

INNODB_TABLES

INNODB_SYS_TABLESPACES

INNODB_TABLESPACES

INNODB_SYS_TABLESTATS

INNODB_TABLESTATS

INNODB_SYS_VIRTUAL

INNODB_VIRTUAL

在MySQL 5.6、5.7和PolarDB MySQL版 5.6、5.7版本中不能存在PolarDB MySQL版 8.0版本新增的同名視圖,在MySQL 5.7或PolarDB MySQL版 5.7版本的叢集中執行如下語句,如果有返回則需要確認如何對此類表進行處理,此項檢查建議您在自建叢集上雲升級時執行。

'indexes',
'parameter_type_elements',
'parameters',
'resource_groups',
'routines',
'schemate',
'st_spatial_reference_systems',
'table_partition_systems',
'table_partition_values',
'table_partitions',
'table_states',
'tables',
'tablespace_files',
'tablespaces',
'triggers',
'view_routine_usage'
);

suppose
+--------------+--------------+
| TABLE_SCHEMA |  TABLE_NAME  |
+--------------+--------------+
|     mysql    |   catalogs   |
+--------------+--------------+
1 rows in set (0.00 sec)

在MySQL 5.6或5.7版本的叢集中執⾏如下語句,如果有返回則需要確認如何對此類表進⾏處理,此項檢查建議您在⾃建叢集上雲升級時執⾏。

SELECT TABLE_SCHEMA, TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE LOWER(TABLE_SCHEMA) = 'mysql'
and LOWER(TABLE_NAME) IN
(
'catalogs',
'character_sets',
'check_constraints',
'collations',
'column_statistics',
'column_type_elements',
'columns',
'dd_properties',
'events',
'foreign_key_column_usage',
'foreign_keys',
'index_column_usage',
'index_partitions',
'index_stats',
'indexes',
'parameter_type_elements',
'parameters',
'resource_groups',
'routines',
'schemata',

上述出現的此類使用者表應在升級前重新命名或刪除,重新命名此類使用者表文法如下:

ALTER TABLE catalogs RENAME user_catalogs;
Query OK, 0 rows affected (0.05 sec)

刪除此類使用者表文法如下:

DROP TABLE catalogs;
Query OK, 0 rows affected (0.06 sec)

視圖相容

在MySQL 8.0版本之前的版本,您最多可以建立具有255個字元的顯示列名的視圖。為遵守列名的最大長度,MySQL 8.0版本不支援顯示列名超過64個字元的視圖,目前這些視圖只能通過在MySQL 5.6、5.7版本中執行SHOW CREATE VIEW來識別。

SHOW CREATE VIEW v1;
+------+------------------------------------------------------------------------------------------------
| View | Create View
+------+------------------------------------------------------------------------------------------------
|  v1  | CREATE ALGORITHM=UNDEFINED DEFINER='root'@'localhost' SQL SECURITY DEFINER VIEW
+------+------------------------------------------------------------------------------------------------
1 row in set (0.00 sec)

因此,您需要在升級8.0版本前修改視圖名稱。

ALTER VIEW v1(a12345678901234567890) AS SECLECT 1;

5.6版本系統資料表相容

mysql.user系統資料表的Password列,在MySQL 5.7.6後的版本及8.0版本中被刪除。所有憑據都儲存在authentication_string列中,包括之前版本儲存在該Password列中的資料。

5.6版本INFORMATION_SCHEMA系統和狀態變數資訊的表相容

MySQL 5.6和PolarDB MySQL版 5.6版本INFORMATION_SCHEMA中包含系統和狀態變數資訊的表在8.0版本中被廢棄,廢棄表如下:

INFORMATION_SCHEMA.GLOBAL_VARIABLES
INFORMATION_SCHEMA.SESSION_VARIABLES
INFORMATION_SCHEMA.GLOBAL_STATUS
INFORMATION_SCHEMA.SESSION_STATUS

8.0版本中將上述廢棄的表遷移至PERFORMANCE_SCHEMA中。

performance_schema.global_variables
performance_schema.session_variables
performance_schema.variables_by_thread
performance_schema.global_status
performance_schema.session_status
performance_schema.status_by_thread
performance_schema.status_by_account
performance_schema.status_by_host
performance_schema.status_by_user

如果您直接使用該視圖,推薦使用SHOW命令代替,而非直接使用相應的視圖。

SHOW VARIABLES
SHOW STATUS

5.6版本INNODB表相容

DYNAMIC替換COMPACT為InnoDB表的隱式預設⾏格式。配置選項innodb_default_row_format指定預設的InnoDB⾏格式,允許DYNAMIC的值包括COMPACT(預設值)和REDUNDANT。升級到8.0後,除⾮您明確定義⾏格式(ROW_FORMAT),否則您建立的任何新表都需要使⽤定義的⾏格式。對於未顯式定義ROW_FORMAT選項或使⽤的現有表ROW_FORMAT=DEFAULT,任何重建表的操作都會將表的⾏格式更改為定義的格式:innodb_default_row_format。更多詳細資料請參見表的⾏格式

5.6版本GET_LOCK函數相容

GET_LOCK()功能在MySQL 5.7.5及之後的版本中使⽤中繼資料鎖定(MDL)⼦系統重新實現,並且其功能已得到擴充:

  • 以前版本中,GET_LOCK()⼀次只允許擷取⼀個命名鎖,第⼆次調用GET_LOCK()時釋放所有現有鎖。8.0版本中GET_LOCK()允許同時擷取多個命名鎖,並且不會釋放現有鎖。

    依賴於GET_LOCK()釋放所有先前鎖的⾏為的應⽤程式必須針對新⾏為進⾏修改。

  • 擷取多個鎖的能⼒可能會在用戶端之間引⼊死結。MDL⼦系統檢測死結且ER_USER_LOCK_DEADLOCK在發⽣這種情況時返回錯誤。

  • MDL⼦系統對鎖名稱添加了64個字元的限制,因此該限制也適⽤於命名鎖。之前版本沒有強制執⾏⻓度限制。

  • 擷取的鎖GET_LOCK()現在出現在Performance Schema metadata_locks中。OBJECT_TYPE列表示USER LEVEL LOCKOBJECT_NAME列表示鎖定名稱。

  • 8.0版本支援RELEASE_ALL_LOCKS()允許⼀次釋放所有獲得的命名鎖。

更多資訊請參見鎖定功能

類型相容

枚舉和集合類型相容

表或預存程序的單個ENUMSET列元素的長度不得超過255個字元或1020個位元組。

5.6版本YEAR類型

廢棄YEAR(2)類型,需要⽤YEAR(4)替換YEAR(2)

5.6版本類型資料插入相容

  • 將負值插⼊⽆符號列時會報錯。樣本如下:

    1. 建立⼀個包含⽆符號列的表:

       CREATE TABLE test (id int unsigned);
    2. 插⼊⼀個負值。

      INSERT INTO test VALUES (-1);
      • 5.6版本中顯示結果如下:

        Query OK, 1 row affected, 1 warning (0.01 sec)
      • 8.0版本中顯示結果如下:

        ERROR 1264 (22003): Out of range value for column 'a' at row 1
  • 資料除以零會報錯。樣本如下:

    1. 建立測試表:

      CREATE TABLE test2 (id int unsigned);
    2. 資料除以零。

      INSERT INTO test2 VALUES (0/0);
      • 5.6版本顯示結果如下:

        Query OK, 1 row affected (0.01 sec)
      • 8.0版本顯示結果如下:

        ERROR 1365 (22012): Division by 0
  • 字元超⻓插⼊報錯。樣本如下:

    1. 將20個字元的字串插⼊10個字元的列會報錯。建立⼀個包含10個字元的列的表:

      CREATE TABLE test3 (a varchar(10));
    2. 插⼊更⻓的字串。

      INSERT INTO test3 VALUES ('abcdefghijklmnopqrstuvwxyz');
      • 5.6版本顯示結果如下:

        Query OK, 1 row affected, 1 warning (0.00 sec)
      • 8.0版本顯示結果如下:

        ERROR 1406 (22001): Data too long for column 'a' at row 1
  • ⾮標準零⽇期插⼊⽇期時間列會報錯。樣本如下:

    1. 建立⼀個包含⽇期時間列的表。

      CREATE TABLE test3 (a datetime);
    2. 插⼊0000-00-00 00:00:00

      INSERT INTO test3 VALUES ('0000-00-00 00:00:00');
      • 5.6版本顯示結果如下:

        Query OK, 1 row affected, 1 warning (0.00 sec)
      • 8.0版本顯示結果如下:

        ERROR 1292 (22007): Incorrect datetime value: '0000-00-00 00:00:00' for column 'a' at ro

5.7版本JSON類型中INT類型資料變化

JSON中的部分INT類型被添加了.0變成類似1.0或者9999.0,初步確認是5.7和8.0版本對JSON裡面雙精確度處理方式不同而導致,解決方案需要做DTS資料校正,如有需求您可以在配置DTS介面配置資料校正。

5.x舊式類型相容

舊式decimal、舊式varchar、舊式TIME/DATETIME和TIMESTAMP等資料類型分別在MySQL 5.0、MySQL 5.1和MySQL 5.6版本中已淘汰,由於二進位升級一直持續到MySQL 5.6、5.7版本,所以在MySQL 8.0版本中不被支援。這些表可以通過在升級前在MySQL 5.6、5.7版本中運行CHECK TABLE...FOR UPGRADE或使用帶有check-upgrade選項的mysqlcheck來識別。此外,使用舊式TIME/DATETIME和TIMESTAMP的表還可以通過啟用會話變數來識別,

check table 41_decimal for upgrade;
+-----------------+-------+----------+------------------------------------------------
| Table           | Op    | Msg_type | Msg_text                                         
+-----------------+-------+----------+------------------------------------------------
| test.41_decimal | check | error    | Table upgrade required for `test`.`41_decimal`. 
+-----------------+-------+----------+-------------------------------------------------
1 row in set (0.00 sec) 
check table 55_temporal for upgrade;
+------------------+-------+----------+------------------------------------------------
| Table            | Op    | Msg_type | Msg_text                                        
+------------------+-------+----------+------------------------------------------------
| test.55_temporal | check | error    | Table upgrade required. Please do "REPAIR TABLE 
1 row in set (0.00 sec) 
nisha@nisha-PORTEGE-Z30-A:~/workspace1/mysql-5.7/dbg-5.7/client/mysqlcheck --user=root 
error    : Table upgrade required for `test`.`41_decimal`. Please dump/reload table to 
test.55_temporal
error    : Table upgrade required. Please do "REPAIR TABLE `55_temporal`" or dump/reloa
test.child                                         OK
test.geom                                          OK
test.jemp                                          OK
test.jemp_myisam                                   OK
test.opening_lines                                 OK

使用此類資料類型的表無法升級,應通過REPAIR TABLE修複,並為舊式varchar、舊式decimal轉儲和重新載入:

REPAIR TABLE 55_temporal; 
+------------------+--------+----------+---------------------------------------------------
| Table            | Op     | Msg_type | Msg_text                                          
+------------------+--------+----------+---------------------------------------------------
| test.55_temporal | repair | Note     | TIME/TIMESTAMP/DATETIME columns of old format have
| test.55_temporal | repair | status   | OK                                                
+------------------+--------+----------+---------------------------------------------------
2 rows in set (0.01)
Dump:
$./client/mysqldump --databases test --socket=5.6/data/mysql.sock --user=root>test.sql
Restore:
.\ test.sql

關鍵詞與保留字

PolarDB MySQL版 8.0版本可以通過 information_schema.KEYWORDS表查看目前的版本的關鍵詞與保留字,不得有關鍵字或保留字違規的情況。PolarDB MySQL版 8.0版本中可能保留了部分以前未保留的關鍵字,詳情請參見關鍵字和保留字。建議所有自訂內容(表名、欄位名、函數名)等全部規避使用。除此之外,KICKOUTPolarDB MySQL版 8.0的保留關鍵字。因此,若您已經在MySQL 5.6、5.7或原生MySQL 8.0版本上使用該關鍵字作為對象名稱(如表名、欄位名、預存程序名等),在遷移到PolarDB MySQL版 8.0版本前,請您先修改對象名稱避免使用該關鍵字,否則遷移時,將會出現錯誤碼為1064的文法報錯。

SQL相容性

GRANT授權

在MySQL 8.0.11中,刪除了部分與賬戶管理相關、已棄用的功能,例如使用GRANT語句修改使用者賬戶的非特權特性。

GRANT REPLICATION CLIENT ON *.* TO 'odps'@'%'; You are not allowed to create a user with
create user;
grant privielges;

不支援GROUP BY ASC/DESC

自MySQL 8.0.13開始,已刪除不推薦使用的子句ASC和DESC限定符GROUP BY,之前依賴GROUP BY排序的查詢可能會產生與之前MySQL版本不同的結果。要產生給定的排序次序,您需要提供一個GROUP BY子句。樣本如下:

將SQL語句:

select id,count(*) from sbtest.sbtest1 where id < 10 group by id desc

改寫為:

select id,count(*) from sbtest.sbtest1 where id < 10 group by id order by id
說明

PolarDB MySQL版 8.0.2.2.11.1版本及以上的版本,不需要執行以上改寫操作。您只需要在控制台上將loose_group_by_compatible_sorting參數的值設定為TRUE,即可直接在SQL語句中使用帶有ASC或DESC的GROUP BY子句。在控制台上設定參數值的操作步驟請參見設定叢集參數和節點參數

外鍵約束定義

在MySQL 5.6、5.7版本中,定義FOREIGN KEY的InnoDB不得帶有CONSTRAINT的關鍵字且指定外鍵約束名稱不得超過64個字元。在MySQL 8.0之前的版本中,當您未明確指定外鍵約束名稱時,InnoDB會通過在表名後附加_ibfk_X來自動產生外鍵約束名稱,其中X是一個數字。如果表名是多位元組64字元,如下面樣本中使用的⻄裡爾表名 имя_базы_в_кодировке_утф8_длиной_больше_чем_45имя_азы_в_кодировк,則自動產生的外鍵約束名稱將超過64個字元。應通過刪除約束並確保外鍵約束名稱不超過64個字元來添加具有顯式約束名稱的約束來更改這些表。

ALTER TABLE `имя_базы_в_кодировке_утф8_длиной_больше_чем_45имя_азы_в_кодировк` DR
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0
ALTER TABLE `имя_базы_в_кодировке_утф8_длиной_больше_чем_45имя_азы_в_кодировк` AD
Query OK, 0 rows affected (0.13 sec)
Records: 0 Duplicates: 0 Warnings: 0

5.7版本空間函數

在MySQL 5.7中,不推薦使⽤多個名稱下可⽤的部分空間函數。樣本如下:

CREATE TABLE t_gcol_dep (fid INTEGER NOT NULL PRIMARY KEY, g POINT GENERATED ALWA
Query OK, 0 rows affected, 1 warning (0.07 sec)
show warnings;
+---------+------+---------------------------------------------------------------------
| Level | Code | Message
+---------+------+---------------------------------------------------------------------
| Warning | 1287 | 'POINTFROMTEXT' is deprecated and will be removed in a future releas
+---------+------+---------------------------------------------------------------------
1 row in set (0.00 sec)

由於空間函數名稱更改,這些空間函數在8.0版本中已被刪除。此更改有助於命名規範保持⼀致,即函數以ST_開頭(精確執⾏操作情況下)或者以MBR開頭(執⾏基於最⼩邊界矩形的操作情況下),使⽤此類函數⽣成的列應在升級前更改。已刪除空間函數的列表請參見Features Removed in MySQL 8.0。您需要更改⽣成的列以使⽤相應的ST_MBR函數。

ALTER TABLE t_gcol_dep MODIFY g POINT GENERATED ALWAYS AS (ST_POINTFROMTEXT(POINT
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0

觸發器相容

MySQL 5.0.17之前的CREATE TRIGGER不⽀持definer屬性。此類具有缺失/空定義器屬性或⽆效建立上下⽂(即character_set_clientcollation_collection、資料庫定序屬性)的觸發器定義⼀直存在導致MySQL 5.6、5.7版本時⽆法升級。這些觸發器可以通過在MySQL 5.6、5.7版本中運⾏帶有檢查升級選項的mysqlcheckCHECK TABLE來識別。

$./client/mysqlcheck --user=root --socket=5.7/data/mysql.sock --databases triggers --ch
triggers.t1
Warning : No definer attribute for trigger 'triggers'.'trg_t1_before_insert'. The trig
Warning : No definer attribute for trigger 'triggers'.'t1_bi'. The trigger will be act
Warning : No definer attribute for trigger 'triggers'.'trg_t1_after_insert_1'. The tri
Warning : No definer attribute for trigger 'triggers'.'trg_t1_after_insert'. The trigg
Warning : No definer attribute for trigger 'triggers'.'trg_t1_after_insert_3'. The tri
Warning : No definer attribute for trigger 'triggers'.'trg_t1_before_update_3'. The tr
Warning : No definer attribute for trigger 'triggers'.'trg_t1_before_update'. The trig
Warning : No definer attribute for trigger 'triggers'.'trg_t1_after_update'. The trigg
Warning : No definer attribute for trigger 'triggers'.'trg1'. The trigger will be acti
status : OK
triggers.t2 OK
check table t1;
+-------------+-------+----------+-----------------------------------------------------
| Table | Op | Msg_type | Msg_text
+-------------+-------+----------+-----------------------------------------------------
| triggers.t1 | check | Warning | No definer attribute for trigger 'triggers'.'trg_t1_
| triggers.t1 | check | Warning | No definer attribute for trigger 'triggers'.'t1_bi'.
| triggers.t1 | check | Warning | No definer attribute for trigger 'triggers'.'trg_t1_
| triggers.t1 | check | Warning | No definer attribute for trigger 'triggers'.'trg_t1_
| triggers.t1 | check | Warning | No definer attribute for trigger 'triggers'.'trg_t1_
| triggers.t1 | check | Warning | No definer attribute for trigger 'triggers'.'trg_t1_

您需要轉儲或重新載入此類觸發器解決此類問題:

Dump:
$./client/mysqldump --databases triggers --socket=5.6/data/mysql.sock --user=root>trigge
Restore:
.\ triggers.sql

用戶端相容性

對於Java應⽤來說,MySQL Connector/J升級到8.0以上版本,串連賬戶需要連接器/J 8.0.9或更⾼版本的 caching_sha2_password。如果未在資料來源中將dataworks設定為utf8,可能會出錯,建議修改資料庫名。在的串連串中增加:characterEncoding=utf8&com.mysql.jdbc.faultInjection.serverCharsetIndex=使Java用戶端在串連中顯性指定session層級字元集。

Unknown system variable 'tx_read_only'相容性

MySQL和 8.0版本中已經刪除tx_read_only環境變更,需要使⽤transaction_read_only代替。

即需要將:

 select @@tx_read_only

改寫為:

select @@transaction_read_only

常見問題

並行查詢導致的排序問題

8.0版本開始⽀持並⾏查詢能⼒,並⾏掃描由於隨機訪問資料會導致MySQL預設串⾏掃描的順序每次隨機變化,尤其是涉及到分⻚的SQL。如果您需要⽣成給定的排序次序,請提供⼀個ORDER BY⼦句保證順序。

5.6版本子查詢問題

5.6版本子查詢中的order by不再起作用,例如:

SELECT *
FROM
(
SELECT * FROM `information_schema`. TABLES
ORDER BY table_name DESC
) AS sg
GROUP BY table_name

內層的order by會被5.7、8.0版本的最佳化器忽略,您需要通過修改語句解決這個問題,最簡單的方法是添加limit使排序生效,例如:

SELECT *
FROM
(
SELECT * FROM `information_schema`. TABLES
ORDER BY table_name DESC limit 10000 # 需要⾜夠⼤的⾏數
) AS sg
GROUP BY table_name

5.6版本派⽣表問題

最佳化器現在以⼀致的⽅式處理⼦句中的派⽣表和視圖,使用FROM以更好地避免不必要的物化,並允許使⽤、產⽣更有效執⾏計劃的下推條件。但在 8.0版本以及修改表之類的語句中, DELETEUPDATE之前實現的派⽣表使⽤合并策略可能會導致ER_UPDATE_TABLE_USED錯誤:

DELETE FROM t1
-> WHERE id IN (SELECT id
-> FROM (SELECT t1.id
-> FROM t1 INNER JOIN t2 USING (id)
-> WHERE t2.status = 0) AS t);
ERROR 1093 (HY000): You can't specify target table 't1'
for update in FROM clause

將派⽣表合并到外部查詢塊中會導致從表中選擇和修改表語句時發⽣錯誤。(物化不會導致問題,因為它實際上將派⽣錶轉換為了單獨的表。)為避免此類錯誤的解決⽅法是在執⾏語句前禁⽤使用系統變數的derived_merge標誌optimizer_switch

SET optimizer_switch = 'derived_merge=off';

derived_merge標誌控制最佳化器是否嘗試將FROM⼦句中的⼦查詢和視圖合并到外部查詢塊中。假設沒有其他規則阻⽌合并,預設情況下,該標誌是on啟⽤合并。設定標誌off阻止合并,可以避免上述描述的錯誤。更多資訊請參見使用合并或實現最佳化派生表和查看引用

UNION語句中,要將ORDER BYLIMIT應⽤於單獨查詢塊SELECT ,請將SELECT⼦句放在括弧內 :

(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10)
UNION
(SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);
說明

在 8.0版本中,要求必須使⽤括弧,MySQL之前的版本可能允許這樣的語句不帶括弧。

相關文檔

What Is New in MySQL 8.0

Changes in MySQL 8.0

準備安裝進行升級

升級到MySQL 8.0?這是你需要知道的...

MySQL官方5.6、5.7、8.0版本差異比較: