Mysql

在 MySQLdump 文件中將表類型從 MyISAM 更改為 InnoDB

  • June 22, 2017

我有幾百個系統在 MariaDB 10.1.x 上執行。在這些系統上,有一個主數據庫,由於各種遺留原因,它必須有 MyISAM 表。我希望為這些擁有所有主 MyISAM 表的 InnoDB 版本的主伺服器生產從屬伺服器。出於操作原因,我寧願不必對ALTER TABLE從屬設備執行各種操作。

我正在考慮(可能很簡單)從主伺服器獲取 MySQLdump 文件作為初始從屬設置的一部分,然後使用某種腳本簡單地更改其CREATE TABLE命令以指定 InnoDB 的表類型而不是 MyISAM。

這是一種明智的方法嗎,還有其他人嘗試過嗎?有沒有更好的方法可以讓我成為一個使用 InnoDB 而不必做大量ALTER TABLEs 的奴隸。

我很希望這是可以自動化/基於腳本的東西,因為我們在該領域實際上有數百個這樣的系統,因此手動升級過程將是勞動密集型的並且非常容易出錯。

順便說一句,我注意到 MySQL/MariaDB 本身在內部使用了許多 MyISAM 表,例如mysql.user表。他們是否出於任何特定原因使用 MyISAM,或者這些表是否也可以安全地轉換為 InnoDB。還是我更好地確保我用來進行轉換的任何腳本都mysql完全避免了數據庫中的表?

我創建了腳本,將儲存引擎從 MyISAM 翻轉到 InnoDB,如下所示:

mysqldump ... | sed 's/ENGINE=MyISAM/ENGINE=InnoDB/' > dump.sql

如果你想看看這是否真的有效,只需如下轉儲模式:

mysqldump --no-data ... | sed 's/ENGINE=MyISAM/ENGINE=InnoDB/' > schema.sql

參考mysql schema,請勿觸碰。為什麼 ???

在 MySQL 5.5 中,mysql 模式中的所有表都是 MyISAM。

mysql> select count(1) table_count,ifnull(engine,'Total') eng
   -> from information_schema.tables where table_schema='mysql'
   -> group by engine with rollup;
+-------------+--------+
| table_count | eng    |
+-------------+--------+
|          22 | MyISAM |
|          22 | Total  |
+-------------+--------+
2 rows in set (0.03 sec)

在 MySQL 5.6 中,這種情況開始發生變化

mysql> select count(1) table_count,ifnull(engine,'Total') eng
   -> from information_schema.tables where table_schema='mysql'
   -> group by engine with rollup;
+-------------+--------+
| table_count | eng    |
+-------------+--------+
|           2 | CSV    |
|           5 | InnoDB |
|          21 | MyISAM |
|          28 | Total  |
+-------------+--------+
4 rows in set (0.00 sec)

以下是 MySQL 5.6 的非 MyISAM 表:

mysql> select table_name,engine from information_schema.tables
   -> where table_schema='mysql' and engine in ('InnoDB','CSV')
   -> order by engine,table_name;
+----------------------+--------+
| table_name           | engine |
+----------------------+--------+
| general_log          | CSV    |
| slow_log             | CSV    |
| innodb_index_stats   | InnoDB |
| innodb_table_stats   | InnoDB |
| slave_master_info    | InnoDB |
| slave_relay_log_info | InnoDB |
| slave_worker_info    | InnoDB |
+----------------------+--------+
7 rows in set (0.00 sec)

如果您將log_output更改為 FILE ,則這兩個 CSV 表是慢速日誌和錯誤日誌。引入了 5 個 InnoDB 表來支持崩潰安全複製(參見文件)。

它不止於此。MySQL 5.7 引入了更多的 InnoDB 表。

mysql> select count(1) table_count,ifnull(engine,'Total') eng
   -> from information_schema.tables where table_schema='mysql'
   -> group by engine with rollup;
+-------------+--------+
| table_count | eng    |
+-------------+--------+
|           2 | CSV    |
|          19 | InnoDB |
|          10 | MyISAM |
|          31 | Total  |
+-------------+--------+
4 rows in set (0.01 sec)

以下是 MySQL 5.7 的非 MyISAM 表:

mysql> select table_name,engine from information_schema.tables
   -> where table_schema='mysql' and engine in ('InnoDB','CSV')
   -> order by engine,table_name;
+---------------------------+--------+
| table_name                | engine |
+---------------------------+--------+
| general_log               | CSV    |
| slow_log                  | CSV    |
| engine_cost               | InnoDB |
| gtid_executed             | InnoDB |
| help_category             | InnoDB |
| help_keyword              | InnoDB |
| help_relation             | InnoDB |
| help_topic                | InnoDB |
| innodb_index_stats        | InnoDB |
| innodb_table_stats        | InnoDB |
| plugin                    | InnoDB |
| servers                   | InnoDB |
| server_cost               | InnoDB |
| slave_master_info         | InnoDB |
| slave_relay_log_info      | InnoDB |
| slave_worker_info         | InnoDB |
| time_zone                 | InnoDB |
| time_zone_leap_second     | InnoDB |
| time_zone_name            | InnoDB |
| time_zone_transition      | InnoDB |
| time_zone_transition_type | InnoDB |
+---------------------------+--------+
21 rows in set (0.17 sec)

請注意,在 MySQL 5.7 中仍有 10 個 MyISAM。他們來了:

mysql> select table_name,engine from information_schema.tables
   -> where table_schema='mysql' and engine='MyISAM';
+------------------+--------+
| table_name       | engine |
+------------------+--------+
| columns_priv     | MyISAM |
| db               | MyISAM |
| event            | MyISAM |
| func             | MyISAM |
| ndb_binlog_index | MyISAM |
| proc             | MyISAM |
| procs_priv       | MyISAM |
| proxies_priv     | MyISAM |
| tables_priv      | MyISAM |
| user             | MyISAM |
+------------------+--------+
10 rows in set (0.00 sec)

為什麼 MyISAM 中還有 10 個表?

  • userdbprocs_privproxies_privtables_privcolumns_priv是儲存使用者授權的表。
  • func包含儲存的函式
  • proc包含儲存過程
  • event包含執行事件的時間表
  • ndb_binlog_index包含 NDB 儲存引擎(MySQL 集群)所需的資訊

這 10 個表很少使用。它們的內容在啟動時載入到 RAM 中,然後從 RAM 中引用。它們不需要是 InnoDB,因為它們是不應通過事務更改的系統級表。

看看如果這 10 個表是 InnoDB 可能會出現的潛在問題:

  • 在事務中執行 GRANT 命令並回滾
  • 在事務中創建儲存過程並回滾
  • 創建一個新使用者,user表崩潰並損壞

可能會導致這些和其他問題,您甚至不會知道它,直到 mysqld 重新啟動並且沒有人可以登錄、執行儲存過程或安排 cron’d 事件。

因此,有充分的理由將這 10 個表保留為 MyISAM。同樣,請不要更改mysql架構中任何內容的儲存引擎。

引用自:https://dba.stackexchange.com/questions/176973