MYSQL 匯入出錯從指定行號擷取檔案(C語言寫的)及注意事項

gaopengtttt發表於2016-09-20
今天同事匯入MYSQL的時候遇到錯誤 匯出檔案大約200G,在大約1.8w行出錯。檔案太大用SED讀取指定行的時候命令報錯,
sed -n '18032,$p' sql.sql >sqlnew.sql

如果檢視任何資訊都非常麻煩,但是
MYSQL報錯的時候出現了一個行號,然後大概推算了一下得出了開始的行號,所以使用C寫了一個小程式,記錄下來

i==18031 是你確定的行號-1 開始。

點選(此處)摺疊或開啟

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include <string.h>


  4. int main(void)
  5. {
  6.         FILE* fd1;
  7.         FILE* fd2;
  8.         int i=0;
  9.         char m;

  10.         char test[4096];

  11.         if(!(fd1=fopen("reslut.sql","r")))
  12.         {
  13.                 printf("file 1 open error!\n");
  14.                 exit(10);
  15.         }
  16.         if(!(fd2=fopen("reslutnew.sql","w+")))
  17.         {
  18.                 printf("file 2 open error!\n");
  19.                 exit(10);
  20.         }
  21.         while(1)
  22.         {
  23.         if(fgetc(fd1) == '\n')
  24.          {
  25.                 i++;
  26.                 if(i==18031)
  27.                 {
  28.                         break;
  29.                 }
  30.          }
  31.         }
  32.         while(!(feof(fd1)))
  33.         {
  34.                 memset(test,0,4096);
  35.                 fread(test,1000,4,fd1);
  36.                 fwrite(test,strlen(test),1,fd2);
  37.         }

  38.         fclose(fd1);
  39.         fclose(fd2);

  40. }
速度還行。
實際上就是根據換行符確定行號然後接著寫入。
寫入完成後使用sed替換了某些字元
sed -i 's/\*\/\;\;/\*\/\$\$/g'  reslutnew.sql
可以完成,sed取行的時候應該是OOM了。

注意:
1、這樣擷取沒有 use database資訊需要自己寫一下然後source
2、這樣擷取MYSQLDUMP語句的頭資訊肯定沒有了要自己寫一下
3、注意關閉binlog set sql_bin_log=0;
4、注意設定 = 0

關於分開匯出表結構和資料 注意事項:
1、表結構中使用--skip-triggers不要匯出trigger,因為觸發器可能導致資料變化,同時trigger是隨表匯出的一定要--skip-triggers
       在某些跨版本的情況下routine都不要匯出,只要建表建庫等語句,注意匯出表結構和匯出表資料都要--skip-trigger 因為不管
        匯出資料還是表結構trigger都會匯出
2、MYSQL庫會在匯入結構的時候插入字典資訊,匯出資料同樣包含了MYSQL的資訊,這個時候再往MYSQL插入資料就會報錯
     處理就是刪除MYSQL資料庫
3、在儲存過程和觸發替換 ;;為$$的過程中因為擔心資料中也有這種資訊
我們使用如下幾次替換:
sed -i 's/\*\/\;\;/\*\/\$\$/g'   替換*/;; 為*/$$
sed -i 's/DELIMITER ;;/DELIMITER $$/g' 替換 DELIMITER ;; 為 DELIMITER $$
sed -i 's/end ;;/end $$/g' 替換 end ;; 為 end $$
4、如果截斷了行進行再次匯入一定注意加上MYSQLDUMP檔案的一些初始的變數設定如:

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

5、如果用MYSQL介面匯入設定一個 --tee log.log 用於記錄插入日誌

關於trigger 還有一點要說明:
trigger本生是隨表匯出的。
也就是不管是after還是before的trigger某個表的觸發器都是在
這個表資料insert以後建立,這樣既保證了trigger的建立也保證了
資料不會變化,但是如果先匯入的是表結構帶了trigger那麼就打破了
這個原則導致資料亂掉。
看如下dump:
LOCK TABLES `mmmm` WRITE;
/*!40000 ALTER TABLE `mmmm` DISABLE KEYS */;
INSERT INTO `mmmm` VALUES (1);
/*!40000 ALTER TABLE `mmmm` ENABLE KEYS */;
UNLOCK TABLES;
/*!50003 SET @saved_cs_client      = @@character_set_client */ ;
/*!50003 SET @saved_cs_results     = @@character_set_results */ ;
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
/*!50003 SET character_set_client  = utf8 */ ;
/*!50003 SET character_set_results = utf8 */ ;
/*!50003 SET collation_connection  = utf8_general_ci */ ;
/*!50003 SET @saved_sql_mode       = @@sql_mode */ ;
/*!50003 SET sql_mode              = 'STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 trigger tri_bb after insert on mmmm
for each row
begin
insert into mmmm1 select count(*) from mmmm;
end */;;
DELIMITER ;
/*!50003 SET sql_mode              = @saved_sql_mode */ ;
/*!50003 SET character_set_client  = @saved_cs_client */ ;
/*!50003 SET character_set_results = @saved_cs_results */ ;
/*!50003 SET collation_connection  = @saved_col_connection */ ;


--
-- Dumping data for table `mmmm2`
--


LOCK TABLES `mmmm2` WRITE;
/*!40000 ALTER TABLE `mmmm2` DISABLE KEYS */;
INSERT INTO `mmmm2` VALUES (1);
/*!40000 ALTER TABLE `mmmm2` ENABLE KEYS */;
UNLOCK TABLES;
/*!50003 SET @saved_cs_client      = @@character_set_client */ ;
/*!50003 SET @saved_cs_results     = @@character_set_results */ ;
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
/*!50003 SET character_set_client  = utf8 */ ;
/*!50003 SET character_set_results = utf8 */ ;
/*!50003 SET collation_connection  = utf8_general_ci */ ;
/*!50003 SET @saved_sql_mode       = @@sql_mode */ ;
/*!50003 SET sql_mode              = 'STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION' */ ;
DELIMITER ;;
/*!50003 CREATE*/ /*!50017 DEFINER=`root`@`localhost`*/ /*!50003 trigger tri_bb1 after insert on mmmm2
for each row
begin
insert into mmmm3 select count(*) from mmmm;
end */;;
DELIMITER ;
/*!50003 SET sql_mode              = @saved_sql_mode */ ;
/*!50003 SET character_set_client  = @saved_cs_client */ ;
/*!50003 SET character_set_results = @saved_cs_results */ ;
/*!50003 SET collation_connection  = @saved_col_connection */ ;


可以看到trigger的建立是在表insert後下一個表以前

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2125234/,如需轉載,請註明出處,否則將追究法律責任。

相關文章