我想將資料庫從 Maria10.1 升級到 Maria10.2,當我運行遷移時,在創建一些表時出現“Mysql Row size too large”錯誤。
一個拋出此錯誤的表有 40 個欄位定義為:
varchar(250) DEFAULT NULL
表本身是:
ENGINE=InnoDB DEFAULT CHARSET=latin1
我想我理解核心問題;innodb 將嘗試存盤大小小于 255 'inline' 的 varchar 欄位,如果一個表有很多這樣的列,它會導致行大小太大而無法容納在單個資料庫頁面中,因此會發生“行大小”錯誤,在Maria10.1上創建此表時不會出現該錯誤。
我發現有 2 個可行的解決方案:
- 將列定義更改為將存盤在“頁外”TEXT、BLOB 或 VARCHAR 大小 > 255 的型別(或大小),這允許將每一列作為 20 位元組參考存盤在行中,而不是將列完全存盤在行。
- 設定 innodb_page_size=64k
這對于新資料庫來說很好,但是我有現有的資料庫需要升級,因為它們在不再受支持的 MariaDB 10.1 上運行。這些現有的資料庫很大,應用這些解決方案會很困難;對于解決方案 2,備份和匯入 TB 資料是“有風險的”且不容易,對于解決方案 1,可能需要考慮性能;也許較慢的查詢和增加的磁盤空間要求?
我的問題:
- 首先; 是否有可用于大型已建立資料庫的替代解決方案,以提供更簡單的升級路徑?
- 其次; 我可能不得不采用解決方案 1,如果我這樣做了,我該如何減輕性能/存盤影響/是否會對性能/存盤產生重大影響?
其他一些相關資訊:
[編輯] 我知道規范化,但由于資料量這不是一個真正的選擇。
所有表都是innodb
關閉 innodb_strict_mode 不是一個選項
非常感謝您的關注!
uj5u.com熱心網友回復:
四十個欄位定義為 varchar(250) DEFAULT NULL
所以SELECT MAX(LENGTH(col1)), ... 對于一些可能的列。
然后設計一個ALTER將一些最小的列縮小到較小的最大值并將接近 250 的任何列更改為TEXT.
另外,請注意升級是否更改了CHARACTER SET遠離latin1。
并注意您將要更改為 TEXT 的任何列是否在任何索引中。如果是這樣,讓我們??更詳細地討論它們。
(這ALTER將需要很長時間,但可能不像添加壓縮那么長,當然也不像更改頁面大小那么長。)
MariaDB 10.3 引入了“存盤引擎獨立列壓縮”,這可能很有用。
uj5u.com熱心網友回復:
我能夠在 MySQL 5.7.34 上重現該錯誤(我不使用 MariaDB)。
我能夠通過將表ROW_FORMAT=COMPRESSED更改為并將列更改為資料型別TEXT而不是 VARCHAR來解決錯誤。這兩種變化都是需要的。帶有 varchar 列的壓縮行格式會導致關于行大小的相同錯誤。
您可能已經知道這一點,但是您不能僅更改一張表的 InnoDB 頁面大小。要更改頁面大小,您必須轉儲所有表(或暫時將它們更改為 MyISAM 或其他存盤引擎),然后關閉 mysqld,洗掉 InnoDB 表空間和日志,更改頁面大小選項,然后重新啟動 mysqld。它將在啟動時使用新的頁面大小初始化新的 InnoDB 表空間和日志。然后你可以將你的表改回 InnoDB。顯然,這會長時間中斷服務。
替代方案可能是設定另一個具有更大頁面大小的服務器實體,并僅在其中存盤該單個表。
但我同意上面來自 O.Jones 的評論——您應該重新考慮在同一行中存盤 40 個長字串列的表設計。這種設計通常是標準化不當的結果。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/367605.html
