2011-05-31 30 views
2

我們使用InnoDB引擎在MySql中存儲了一個非常大的(10百萬以上)行表。列'x'被定義爲'smallint(5)unsigned not null'。InnoDB上的MySql數值類型遷移

自從幾年前的原始設計以來,需求已經發生變化,而'x'列需要存儲最小數據類型大小'int unsigned not null'。

我們被允許「短暫」停機以部署應用程序(少於5分鐘),因此如果數據庫表需要暫時以任何方式暫時不可用(例如,全表鎖)。如果更改可以「在線」完成,那麼我們可能會接受較長時間的性能下降。

有沒有人有過在非常大的表上更改MySql/InnoDB中的列類型的經驗?如果是這樣,它是否行得通,大致需要多長時間(我意識到這是硬件依賴的,我只是想了解我們在時間窗口中要求做的事情是否甚至有可能)?

由於提前,

+0

多久,當你在測試實驗室應用到一個同樣大小的桌子上生產高檔五金沒ALTER TABLE走? – MarkR 2011-05-31 19:18:22

+0

@MarkR - 正在進行中,但可能需要一段時間才能將環境設置爲脫離我的團隊控制。因此,試圖在此期間獲得可行性的想法... – Scruffers 2011-05-31 19:48:22

回答

1

繼承人我用

,你有舊列配方,一個

  1. 創建一個新的B柱
  2. 創建觸發器來更新b在更新/插入上
  3. 更新b = a
  4. 刪除所有fkey關係引用
  5. 創建對於B FKEY關係
  6. 更新代碼,而不是使用B列(部署)
  7. 滴在列
  8. 刪除列觸發

重複所有步驟,如果你必須改變列名返回。

+0

謝謝!這是一個非常有趣的想法 - 我需要考慮它,但它可能只適用於我們... – Scruffers 2011-05-31 19:46:21

0

您可以通過創建一個新表作爲原始佈局的克隆來聯機。

CREATE TABLE newtable LIKE oldtable; 

其次,改變你的新表的字段,以滿足新規範

ALTER TABLE newtable ... ; 

一旦這樣做了,複製的數據。

INSERT INTO newtable SELECT * FROM oldtable; 

最後,用你幾分鐘的停機時間,以你的舊錶重命名爲別的東西,然後給你的新表舊錶的名稱。

當然,您需要有足夠的存儲空間來存放兩張表格。此外,在複製操作期間,您可能希望在執行復制時禁用新表上的索引以減少服務器上的壓力。

一旦您確信舊錶中的所有數據都已被複制到新的數據庫中,您可以最終完全刪除舊錶。

編輯:

其實,更好的方法可能是剛加入新列到符合您要更新列的新要求,現有的表,舊列的值複製到新的列,刪除舊列並將新列重命名爲舊列的名稱。它肯定會降低您的存儲需求。另外,如果您有任何取決於相關列的FK約束,您需要在啓動之前將其刪除,並在完成後將其恢復到新列。

+0

以及在複製操作過程中添加到表中的數據/修改了哪些數據? – fvu 2011-05-31 19:08:17

+0

謝謝,但是我分享了@fvu的關注,因爲這張表是由每次交易觸及應用服務器(即每分鐘多次)更新的。 – Scruffers 2011-05-31 19:44:18

+0

好吧,這是一個很好的觀點,沒有想到這一點。我想你可以實現一個觸發器來保持兩個列/表同步,直到你準備好切換。 – GordonM 2011-06-01 05:34:46

0

你現在有什麼樣的高可用性解決方案?

我問,因爲5分鐘是不夠的停機時間,以允許重新啓動正常的任務,如操作系統更新。

因此,您必須擁有某種高可用性解決方案,以允許這些常規(我假設您的操作團隊會不時應用補丁)更新。

應該可以使用這樣的系統來做到這一點。但是,ALTER TABLE允許表在整個運行過程中始終保持讀取操作的可用狀態,並且只有塊在最後短時間讀取(大多數系統上的讀取時間少於5分鐘)。

所以問,你什麼時候可以合理地阻止寫入?

另外,10M行不是一個大的表,通過任何想象力。它可能適合公羊,因此將很快改變。

+0

對於高可用性:負載均衡器後面的兩個無狀態應用服務器意味着它們可以獨立取消用於操作系統補丁等。但是,兩個應用服務器共享相同的數據庫狀態,這是我們所關注的狀態,因爲我們無法阻止寫入這個表在所有應用服務器啓動時,如果它們停止運行,那就是5分鐘(ish)窗口進入的地方。 – Scruffers 2011-05-31 19:40:15

+0

關於規模:很有用10M不是「大」,我們正在進行一些性能測試這很有趣,看看這是否是一個非問題... – Scruffers 2011-05-31 19:42:44

0

這種做法是相當快

Query OK, 10000000 rows affected (6 min 0.14 sec) 

mysql slow query