日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

mysql5.6最好的备份方案_Mysql 5.6迁移至PostgreSQL 9.6的实践小结

發布時間:2024/10/14 69 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql5.6最好的备份方案_Mysql 5.6迁移至PostgreSQL 9.6的实践小结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、背景

實際生產中,發現mysql查詢性能存在抖動,同樣的sql,正常執行時間是秒級,但是偶爾會有執行上百秒的情況出現,經過DBA的排查,并沒有發現mysql的問題??紤]遷移一部分生成數據到PG中進行測試。(ps~個人覺得這個遷移背景有點牽強,還是應該先定位性能抖動的原因比較好)

二、遷移方案

遷移的大致步驟如下:

從生產環境的mysql備份中拉取一個備份出來

在測試機上通過備份恢復生產庫

導出mysql的表定義和數據

通過自己開發的小工具,將mysql表定義語法轉換至PG的表定義語法

在PG中創建表

將數據導入PG

三、遷移步驟說明

3.1 拉取備份

這個沒什么好說的,scp指定的備份文件到測試機即可

考慮是生產環境,有防火墻和權限等的限制,可以臨時創建臨時用戶tmp,關閉防火墻,待拷貝完成,刪除用戶,重啟防火墻

3.2 恢復生產庫

生產上通過xtrabackup做的備份,恢復方法這里就不啰嗦了,不是本次的重點,自行百度~

3.3 導出mysql的表定義和數據

從這步開始就有坑了~

首先,導出表定義(只貼出測試數據)

# 將名為test_db的庫中所有的ddl都導出到test_db.sql文件中

# 導出的定義以sql語句的形式寫入文件

[mysql@sndsdevdb01 ~]$ mysqldump -h127.0.0.1 -uroot -ppassword -d test_db > /mysql/test_db.sql

[mysql@sndsdevdb01 ~]$ cat /mysql/test_db.sql

...

/* 下面是導出的表定義部分 */

DROP TABLE IF EXISTS `tb1`;

/*!40101 SET @saved_cs_client = @@character_set_client */;

/*!40101 SET character_set_client = utf8 */;

CREATE TABLE `tb1` (

`c1` int(11) DEFAULT NULL,

`c2` char(5) DEFAULT NULL,

`c3` varchar(10) DEFAULT NULL,

`c4` datetime DEFAULT NULL

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

/*!40101 SET character_set_client = @saved_cs_client */;

SET @@SESSION.SQL_LOG_BIN = @MYSQLDUMP_TEMP_LOG_BIN;

/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;

...

導出表定義是為了之后人工檢查mysql到PG的ddl語法轉換的正確性

實際實施時,利用小工具直接連接mysql服務器即可完成mysql到PG的ddl語法轉換

關于小工具的說明,請見附錄~

然后,導出數據

考慮到數據格式,編碼的問題,決定統一將數據導出為UTF8編碼的csv文件

為了說明坑的地方,我插入了5條記錄

mysql> delete from tb1;

Query OK, 3 rows affected (0.01 sec)

mysql> insert into tb1 values(1,'qqq','www',current_time);

Query OK, 1 row affected (0.02 sec)

mysql> insert into tb1 values(1,'qq\nq','www',current_time);

Query OK, 1 row affected (0.01 sec)

mysql> insert into tb1 values(1,'qq\r\nq','www',current_time);

Query OK, 1 row affected (0.00 sec)

mysql> insert into tb1 values(1,'qqq','www','0000-00-00 00:00:00');

Query OK, 1 row affected (0.00 sec)

mysql> insert into tb1 values(1,'qqq','www',null);

Query OK, 1 row affected (0.00 sec)

mysql> select * from tb1;

+------+-------+------+---------------------+

| c1 | c2 | c3 | c4 |

+------+-------+------+---------------------+

| 1 | qqq | www | 2017-07-14 17:36:25 |

| 1 | qq

q | www | 2017-07-14 17:36:30 |

| 1 | qq

q | www | 2017-07-14 17:36:36 |

| 1 | qqq | www | 0000-00-00 00:00:00 |

| 1 | qqq | www | NULL |

+------+-------+------+---------------------+

5 rows in set (0.00 sec)

mysql> select * from tb1 into outfile '/mysql/tb1.csv' fields terminated by ',' optionally enclosed by '"' escaped by '"' lines terminated by '\n';

其中第二條和第三條中,c2列分別包含了換行符和windows的特殊換行符

然后再通過vi 打開tb1.csv

1,"qqq","www","2017-07-14 17:36:25"

1,"qq"

q","www","2017-07-14 17:36:30"

1,"qq^M"

q","www","2017-07-14 17:36:36"

1,"qqq","www","0000-00-00 00:00:00"

1,"qqq","www","N

坑點如下

\n換行符導致原本的一條記錄分為2行

\r是特殊字符,vi模式下就表示為^M

datetime類型可以存儲"0000-00-00 00:00:00",但是官方手冊上datetime的合法范圍是'1000-01-0100:00:00' to '9999-12-31 23:59:59',感覺是bug。。

NULL值會被轉義為"N的形式

1和2兩點,導致csv格式混亂,導入PG會出錯;datetime對應PG的timestamp類型,而"0000-00-00 00:00:00"是不符合PG的時間戳類型的合法范圍的;PG也不認識"N表示的NULL。。。

由于上述的坑都是在將數據導入PG的時候才發現的,所以我的做法是通過shell的sed,awk等命令,去人工替換這些內容。因為生產數據量很大,一個庫大概200G,磁盤空間有限,加上導出數據需要較長時間,所以盡量不重復導數據

但是用shell處理大文件,效率也很低,150G的csv文件,遍歷sed多次,往往超過1小時,而且存在正則表達式寫的不精確,匹配出錯的情況

所以我個人推薦,select導出數據時,通過where條件過濾,用replace函數將需要處理的列直接處理掉,可以省去后面的麻煩,但是前提條件是需要知道有哪些列存在這些問題(生成中的表往往列很多,幾十甚至幾百列)

3.3 在PG中創建表并導入數據

首先創建相應的業務庫

postgres=# create database test_db;

CREATE DATABASE

postgres=# \c test_db

You are now connected to database "test_db" as user "postgres".

postgres=#\i /pgsql/pg.sql

# 執行轉換后的ddl,定義表

...

postgres=#\copy tb1 from '/pgsql/tb1.csv' with(format csv,encoding 'UTF8',NULL 'null')

# 通過copy命令導入數據,通過指定NULL字符串來識別NULL值

如果導入過程不出現任何錯誤,那說明數據的遷移基本就完成了

3.4 其他

上述內容只是單純的業務庫的數據遷移,如果想完整的把整個業務系統遷移至PG,還有很多的別的遷移工作

例如表的索引

PG提供了豐富的索引類型,索引詳情參考:

PG 9.6 手冊 http://www.postgres.cn/docs/9.6/indexes.html

需要根據業務需求重新定制,例如AP型業務,gin索性就有很大的優勢,除此之外,業務定義的存儲過程,上層的增刪改查接口等等也需要修改

另外,數據庫的備份方案,日志歸檔設置,高可用方案的設計這些也需要定制

附錄

關于DDL語法轉換的小工具

功能簡述

將mysql的表定義轉換為PG對應的語法。主要完成數據類型的映射,列屬性語法的轉換,主鍵和部分類型索引的轉換

1.1. 類型映射

case "tinyint":

case "tinyint unsigned":

case "smallint":

if (col_is_auto_increment.equals("YES")){//increment type

mysql_type.add("smallserial");

}else{

mysql_type.add("smallint");

}

break;

case "mediumint":

case "smallint unsigned":

case "mediumint unsigned":

case "integer":

case "int":

if (col_is_auto_increment.equals("YES")){//increment type

mysql_type.add("serial");

}else{

mysql_type.add("int");

}

break;

case "int unsigned":

case "bigint":

if (col_is_auto_increment.equals("YES")){//increment type

mysql_type.add("bigserial");

}else{

mysql_type.add("bigint");

}

break;

case "bigint unsigned":

mysql_type.add("decimal");

mysql_type.add("20");

mysql_type.add("0");

break;

case "double":

mysql_type.add("double precision");

break;

case "decimal":

mysql_type.add("decimal");

mysql_type.add(precision.toString());

mysql_type.add(scale.toString());

break;

case "float":

mysql_type.add("real");

break;

case "binary":

case "char":

mysql_type.add("char");

mysql_type.add(precision.toString());

break;

case "varbinary":

case "varchar":

mysql_type.add("varchar");

mysql_type.add(precision.toString());

break;

case "tinyblob":

case "mediumblob":

case "longblob":

case "blob":

mysql_type.add("bytea");

break;

case "date":

mysql_type.add("date");

break;

case "datetime":

case "year":

case "timestamp":

mysql_type.add("timestamp");

break;

case "time":

mysql_type.add("time");

break;

/*case "bit":

pg_type.add("bit");

break;*/

case "tinytext":

case "text":

case "mediumtext":

case "longtext":

mysql_type.add("text");

break;

default:

mysql_type.add("This type may be user deifned type,confirm for yourself please!");

break;

1.2. 列屬性

* not null屬性

* column注釋

* 自增屬性

1.3. 索引

統一將mysql的索引轉換為PG的btree索引,這個在應用中意義不大,因為多數情況,索引是需要根據業務需求重新定義的

實現方式

通過JDBC連接mysql服務器,通過元數據(metadata)獲取所有的表名,列名以及列的數據類型等等信息,然后在程序中做轉換,最后寫入sql文件

思考

其實這只是簡單的遷移方案,目前也有一些商用或者開源的遷移工具,例如:

mysql2pg:https://sourceforge.net/projects/mysql2pg/

另外,關于遷移數據,用csv文件的方式,對磁盤空間的要求較高,而且有上述字符格式的問題。其實還可以考慮PG的插件mysql_fdw,可以直接用select into的方式將數據直接插入PG中,可以省去中間導出的步驟。但是9.6的PG,對foreign table的語法支持不完善,不支持like的方式建表,所以對寬表,create foreign table寫起來就比較麻煩,可以考慮用腳本自動化。

另外,生產中往往mysql和PG不在一臺機器上,mysql_fdw拉取和插入數據的效率還有待測試。我初步的嘗試發現,速度是很慢的,不過沒有深入調查原因,有可能是網絡問題,也有可能是配置問題

mysql_fdw的說明參考德哥的博客:http://blog.163.com/digoal@126/blog/static/163877040201493145214445/

總結

以上是生活随笔為你收集整理的mysql5.6最好的备份方案_Mysql 5.6迁移至PostgreSQL 9.6的实践小结的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。