記一次數據庫遷移的過程採坑過程

業務場景

最近的一個項目最開始因爲資源問題,mysql 數據庫是部署在一臺雲服務器上的,這兩天客戶提供了雲數據庫,因此原來在部署在 ECS 服務器上的數據庫,須要遷移到雲數據庫。在雲數據庫上的優點不少,它自動是分配了一主二從,自動備份等。因此這兩天的任務就是要將原來的數據庫遷移。 mysql 版本 mysql5.7.17mysql

遷移步驟

遷移數據庫是一項須要很謹慎的任務。整個遷移過程大概分紅如下幾步:sql

  1. 備份原數據庫數據
//備份數據庫,並指定日期
mysqldump -uadmin -p****** databaseName | gzip > /databak/databaseName_$(date +%Y%m%d).sql.gz
  1. 雲數據庫上初始化數據庫、編碼、用戶名、數據庫等基礎信息 先經過騰訊雲平臺建立用戶,以及相關權限
//鏈接數據庫
mysql -h172.16.0.1 -uUserName -p******
//建立數據庫,並指定編碼
CREATE DATABASE databaseName DEFAULT CHARACTER SET  utf8mb4 COLLATE utf8mb4_general_ci;
  1. 執行還原操做
//解壓備份好的.sql文件
gunzip -v /databak/databaseName_20200517.sql.gz
//還原數據庫
source /databak/databaseName_20200517.sql

產生的問題

正常狀況下,按照以上遷移數據的步驟,應該等還原操做完成便可,可是事情每每不會那麼順利,若是很順利可能咱們對數據庫遷移的認知就到這裏就能夠了。數據庫

實際上在執行還原操做時出現了錯誤。 主要出現兩次問題服務器

  1. 沒有主鍵
ERROR 1173 (42000): This table type requires a primary key
  1. 表的存儲引擎不對
Can not create tables in myisam storage engine in user databases, controled by reject_create_table_myisam variable.

看到這兩個問題,感受比較奇怪,由於最開始在測試數據庫自動備份時,已經對備份的sql文件還原過,沒有發現有什麼錯誤。爲何這一次遷移就出現這兩個問題呢?分佈式

排查方法

建表缺乏主鍵

針對問題1,看日誌比較容易明白意思,就是表須要主鍵,這個時候就想先看看數據庫中有哪些沒有主鍵的表,看看可否直接指定。測試

查詢沒有主鍵的表的sql以下:ui

SELECT table_schema, table_name,TABLE_ROWS
FROM information_schema.tables
WHERE (table_schema, table_name) NOT IN (
SELECT DISTINCT table_schema, table_name
FROM information_schema.columns
WHERE COLUMN_KEY = 'PRI'
)
AND table_schema NOT IN ('sys', 'mysql', 'information_schema', 'performance_schema');

查詢結果分析發現這些表和錯誤日誌中的表匹配。而後查看了兩張表發現的確都是沒有指定主鍵的。正常 mysql 的設計中,若是在建立表時沒有顯式地定義主鍵,則 InnoDB 存儲引擎會按以下方式選擇或建立主鍵:google

  1. 首先判斷表中是否有非空的惟一索引,若是有,則該列即爲主鍵。
  2. 若是不符合上述條件,InnoDB存儲引擎自動建立一個6字節大小的指針。

可是仍是報那個錯。這時在想是否和數據庫的版本有關係。通過 google 搜索大部分的結果都是定位到數據庫的參數設置了表必定要指定主鍵。編碼

解決辦法以下:設計

//查詢變量查看是否開啓了強制主鍵,也就是建表必須有主鍵約束,
show global variables like 'innodb_force_primary_key';
//若是是ON則設置成OFF便可
set global  innodb_force_primary_key=off;

固然我也找找這個方法去嘗試了,但我執行第一句時,發現沒有找到結果。而後也通過了解這個參數是mysql8.0以及MariaDB中才有這個參數。強制執行

set global  innodb_force_primary_key=off;

出現以下錯誤:

ERROR 1193 (HY000): Unknown system variable 'innodb_force_primary_key'

因此這種方法行不通。但經過這個解決方法,我猜想問題可能就是和變量設置有關係,因而我查看了全部的 mysql 全局變量,最後找到了問題所在。

問題定位:原來騰訊雲上的分佈式數據庫tdsql中,設置建表須要主鍵的參數爲 reject_table_no_pk 這個時候就能定位到問題所在了。

表的存儲引擎不對

經過以下sql能夠查詢一個庫中全部使用MyISAM存儲引擎建立的表

SELECT * FROM information_schema.tables where engine='MyISAM' and TABLE_SCHEMA='databaseName'

查出來的表和還原錯誤日誌報錯的表也匹配了。

經過分析問題1時,在查找全局變量時存在以下變量。

reject_create_table_myisam 意思就是拒絕使用 myisam 存儲引擎建表。因此問題2也定位到了問題源頭。

解決方案

經過上面一步一步分析問題,已經找到了問題的源頭,找到了問題的產生緣由。對於問題的解決就比較好處理了。

方法1

登陸超級管理員,對這兩個參數進行設置

set global reject_table_no_pk 0;
set global reject_create_table_myisam OFF;

設置完成以後,從新執行還原操做,發現問題解決。可是分佈式數據庫新增了的這兩個參數實際上是有他的用處的,這種默認值最好不要輕易調整,由於雲數據庫還有一個優點就是大部分的參數都調成了最佳。

經過資料搜索發現原來這兩個參數是有重要做用的。 TDSQL 內核使用 row 格式的 binlog 複製。根據目前 MariaDB/MySQL 的實現方式,若是一個 update/delete 語句更新或者刪除了不少行,那麼到了備機上面,更新或者刪除每一個行時候,須要使用索引掃描或者全表掃描來找到這個行,致使備機複製變得很是慢,這是很是嚴重的問題。 在 TDSQL 的告警平臺上面就有用戶出現過主備延遲所以變得很是大的告警。爲了不這些致命問題的出現,因此纔有「自動增長主鍵」和「禁止 create table/alter table 語句產生無主鍵的表」

方法2

方法1可以解決還原問題,也可以解決通常數據量不大的應用。可是若是後面業務增加,可能仍是須要將參數調整回來。此時方法1的解決方案就行不通了。

方法2實際就是針對沒有主鍵的表設置主鍵,沒有主鍵的表新增主鍵。以符合分佈式數據庫要求。

而對於數據庫存儲引擎爲myisam的表經過sql語句直接調整。

//修改表的存儲引擎
alter table table_name engine=innodb;

總結

數據庫內容不少,很深,咱們在處理工做中實際問題時,須要多多思考。從解決實際問題的過程當中去深刻知識點,擴展知識點。這樣才能提升。

相關文章
相關標籤/搜索