linux下如何增量增量传输mysql binlog日志

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
日志服务 SLS,月写入数据量 50GB 1个月
简介: 在实际的工作中我们遇到了一个问题,MYSQL 5.5 我们备份使用的mysqldump,然后每天传输的备份到备份机器,但是binlog却不好传输主要要考虑几个问题: 1、binlog 没法取时间,按照什么规则来传? 2、binlog的传输并不是每次都全部传输过去,而是需要增量的。
在实际的工作中我们遇到了一个问题,MYSQL 5.5 我们备份使用的mysqldump,然后每天传输的备份到备份机器,但是binlog却不好传输主要要考虑几个问题:
1、binlog 没法取时间,按照什么规则来传?
2、binlog的传输并不是每次都全部传输过去,而是需要增量的。
3、binlog的最后一个日志是在使用的是不能传输的。
4、为了更通用需要使用一个前缀,因为每个数据库的binlog前缀是可以自己指定的
如 mysqlbin.000001

那么有了上面的问题,如何解决?也许shell脚本能够完成,但是我选择使用C/C++ 和LINUX系统函数 opendir readdir lstat来完成
这是我最后挂载的脚本
#!/bin/sh
TIME_TAG=`date +%Y%m%d`
/root/ftptool/tool  /dbdata/data/  /root/ftptool/ mysql-bin > tool_${TIME_TAG}.log
if [ $? != 0  ]; then
    echo "tool failed"
    exit
else
    echo "tool sucess!"
fi
cat /root/ftptool/ftphead > /root/ftptool/ftp_TIMETAG.shcat/root/ftptool/{TIME_TAG} >> /root/ftptool/ftp_{TIME_TAG}.sh  cat /root/ftptool/ftptail >> /root/ftptool/ftp_{TIME_TAG}.sh


chmod 755 /root/ftptool/ftp_${TIME_TAG}.sh
sh /root/ftptool/ftp_${TIME_TAG}.sh
实际上
ftp_${TIME_TAG}.sh来自3个部分
1、
ftphead --这个很简单自己写明白ip 用户名密码就好了,如下:
#!/bin/sh

ftp -i -v -n<< EOF
open 192.168.*.*
user mysql ****
cd /backup/mysql
bin
2、 ftptail  这个更简单
quit
EOF
就这点
3、
cat ${TIME_TAG}
这部分是我自己写的工具
tool 生成的
工具使用如下:
Usage:./tool binlogdir ftpdir binlogprefix
需要一个binlog目录 一个ftp目录和binlong的前缀
binlog目录不用多说是binlog的所在目录,需要以/结尾比如 /mysql/data/不能是/mysql/data 否则抛错error 20 binlogdir Must End With /

ftp目录下存放两个东西一个tmp文件和生成的ftp脚本,ftp脚本生成和当前时间一致比如20160713
tmp文件用于存放当前取到的最大的binlog序号,如果不存在可以新建一个,如果不新建抛错error 15 tmp file not found
如果想再次全部传输删除tmp文件新建一个空的就可以比如touch tmp
这个ftp目录同样必须使用/结尾 否则抛错error 21 ftpdir Must End With /

binlogprefix 就是你的前缀比如mysql-bin

使用就是这么简单,有了这3部分就能够通过shell
cat ftphead > ftp_${TIME_TAG}.sh
cat {TIME_TAG} >> ftp_{TIME_TAG}.sh
cat ftptail >> ftp_${TIME_TAG}.sh
生成一个全部的脚本。然后运行了。
另外tool工具会输出一些信息,当然可以关闭,这些输出信息我重定向到了 tool_${TIME_TAG}.log
可以查看下面就是一份:
WARNING:Ftpdir Less Than 1000 Char!
PROCESS:Create Chain Now:
INFO:Current Binog Dir Is :/dbdata/
PROCESS:Checkbin Binlogprefix: mysql-bin
................. 这里省略很多
PROCESS:Print chain info
................. 这里省略很多
PROCESS:Now Acc Ftpdir:
INFO:Ftp_scirpt fun time:
Wed Jul 13 14:44:13 2016
20160713
INFO:Ftp_scirpt Fun Tmpfile :/root/ftptool/tmp
INFO:Tmpfile Write Mode Succ!
INFO:Ftp_Scirpt Fun Tmp_max_st:0 Max_st_1:2028:
INFO:Scan Put Counter :163
INFO:Current Max Binlog-1 is:2028
PROCESS:Free Node Is:164

可以清楚看到将会生成163个put脚本信息,最高的传输是2028,实际最大是2029,我在编码的时候做了-1操作,目的在于不要传输当前的binlog,
因为当前的binlog正在使用

最后释放了链表节点164个.同事你的tmp文件目录也会输出,binglog 的目录也会输出.

下面是全部分出错码:
error 10 open bindbr error
error 11 argv parameter error
eroor 12 not find binlog
error 14 fptdir open error
error 15 tmp file not found
error 16 lstat tmp file error
error 18 tmp file write error
error 20 binlogdir Must End With /
error 21 ftpdir Must End With /
当然成功放回 0

编译好的我放到了百度云盘
http://pan.baidu.com/s/1i4WuBB3
下面是全部的源代码
编译使用 g++ main.cpp mybin.cpp -o tool 即可 注意本工具使用了LINUX系统函数所以必须是LINUX系统或者其他满足posix标准的系统不包含windows
在LINUX下编译没有问题。有什么问题可以联系QQ 22389860.

点击(此处)折叠或打开

  1. /*************************************************************************
  2.   > File Name: mbin.h
  3.   > Author: gaopeng
  4.   > Mail: gaopp_200217@163.com
  5.   > Created Time: Tue 02 Aug 2016 05:57:27 PM CST
  6.  ************************************************************************/

  7. #include<iostream>
  8. #define _DEG
  9. using namespace std;
  10. typedef unsigned char uchar;
  11. typedef unsigned long ulong;
  12. typedef unsigned int uint;
  13. typedef unsigned short ushort;


  14. typedef struct data
  15. {

  16.     char* file_name;
  17.     char* path_name;
  18.     char* full_name;
  19.     ulong file_st;
  20.     uint nuse;
  21. } DATA;

  22. typedef struct f_node
  23. {

  24.     struct f_node *next;
  25.     DATA* data;
  26. } F_NODE;

  27. typedef struct quence
  28. {

  29.     F_NODE* first;
  30.     F_NODE* last;
  31.     int items;
  32. } QUE;

  33. uint checkbin(const char* file_name,const char* binprefix);
  34. F_NODE* create_que(const char *bindir,const char* binprefix);
  35. QUE* ini_que(void);
  36. void show( F_NODE* const frs_nd);
  37. void ins_chan(const char* f_name,const char* p_name,const char* ful_name,QUE * que);
  38. ulong char_to_num(const char* file_name);
  39. void time_to_time(char* ltime,char* mytime);
  40. void ftp_script(const char* ftp_dir,F_NODE* frs_nd);
  41. int get_max_st(F_NODE* const frs_nd);
  42. ulong readtmp(FILE *fd,const char* tmpdir);
  43. int myfree(F_NODE* const frs_nd);
  44. uint checkdir(const char* mychar);


点击(此处)折叠或打开

  1. /*************************************************************************
  2.   > File Name: main.cpp
  3.   > Author: gaopeng
  4.   > Mail: gaopp_200217@163.com
  5.   > Created Time: Tue 02 Aug 2016 05:58:15 PM CST
  6.  ************************************************************************/

  7. #include<iostream>
  8. #include<iostream>
  9. #include<stdio.h>
  10. #include <sys/types.h>
  11. #include <dirent.h>
  12. #include <string.h>
  13. #include"mbin.h"
  14. #include <stdlib.h>

  15. using namespace std;



  16. int main(int argc,char *argv[])
  17. {
  18.     F_NODE* frs_nd=0;
  19.     int freeno =0;
  20.     printf("%s\n","Usage:./tool binlogdir ftpdir binlogprefix");
  21.     if(argc<4)
  22.     {
  23.         cout<<"ERROR(9):Parameter Error Like:"<<endl;
  24.         printf("%s\n","Usage:./tool binlogdir ftpdir binlogprefix");
  25.         exit(9);
  26.     }
  27.     if(checkdir(argv[1]) == 1)
  28.     {
  29.         cout<<"ERROR(20):binlogdir Must End With /"<<endl;
  30.         exit(20);
  31.     }
  32.     if(checkdir(argv[2]) == 1)
  33.     {
  34.         cout<<"ERROR(21):ftpdir Must End With /"<<endl;
  35.         exit(21);
  36.     }
  37.     printf("WARNING:Ftpdir Less Than 1000 Char!\n");
  38.     printf("PROCESS:Create Chain Now:\n");
  39.     frs_nd = create_que(argv[1],argv[3]);
  40.     cout<<"PROCESS:Print chain info"<<endl;
  41.     show(frs_nd);
  42.     cout<<"PROCESS:Now Acc Ftpdir:"<<endl;
  43.     ftp_script(argv[2], frs_nd);
  44.     
  45.     freeno = myfree(frs_nd);
  46.     cout<<"PROCESS:Free Node Is:"<<freeno<<endl;

  47. return 0;
  48. }


点击(此处)折叠或打开

  1. /*************************************************************************
  2.   > File Name: mybin.cpp
  3.   > Author: gaopeng
  4.   > Mail: gaopp_200217@163.com
  5.   > Created Time: Tue 02 Aug 2016 05:57:34 PM CST
  6.  ************************************************************************/

  7. #include<iostream>
  8. #include "mbin.h"
  9. #include <sys/types.h>
  10. #include <sys/stat.h>
  11. #include <unistd.h>
  12. #include <time.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <dirent.h>
  17. #include <math.h>

  18. using namespace std;

  19. QUE* ini_que(void)
  20. {
  21.     QUE* que = new QUE;
  22.     que->first =0;
  23.     que->last =0;
  24.     que->items =0;
  25.     return que;
  26. }

  27. void ins_chan(const char* f_name,const char* p_name,const char* ful_name,QUE * que)
  28. {
  29.     F_NODE *add = new F_NODE; //inital node pointer
  30.     DATA *name = new DATA; //inital data pointer
  31.     name->file_name = new char[strlen(f_name)+5];
  32.     name->path_name = new char[strlen(p_name)+5];
  33.     name->full_name = new char[strlen(ful_name)+5];

  34.     //init mem

  35.     memset(name->file_name,0,strlen(f_name)+5);
  36.     memset(name->path_name,0,strlen(p_name)+5);
  37.     memset(name->full_name,0,strlen(ful_name)+5);

  38.     name->file_st = char_to_num(f_name);
  39.     name->nuse = 0;
  40.     strcpy(name->file_name,f_name);
  41.     strcpy(name->path_name,p_name);
  42.     strcpy(name->full_name,ful_name);

  43.     add->next =0;
  44.     add->data = name;

  45.     if( que->items==0)
  46.     {
  47.         que->first =add;
  48.         que->last =add;
  49.         que->items++;
  50.     }
  51.     else
  52.     {
  53.         que->last->next = add;
  54.         que->last = add;
  55.         que->items++;
  56.     }
  57. }

  58. F_NODE* create_que(const char *bindir,const char* binprefix)
  59. {
  60.     struct dirent *DirEntry=0;
  61.     DIR* Dir=0;
  62.     QUE* myq=0;
  63.     uint nob=0; //check if binlog find

  64.     myq = ini_que();
  65.     F_NODE* frs_nd =0;

  66.     if( !(Dir = opendir(bindir)))
  67.     {
  68.         perror("ERROR(10):Open Binlog Dir Error:");
  69.         exit(10);
  70.     }
  71.     else
  72.     {
  73.         printf("INFO:Current Binog Dir Is :%s\n",bindir);
  74.         while( DirEntry = readdir(Dir))
  75.         {
  76.             if(DirEntry->d_type == DT_REG && checkbin(DirEntry->d_name,binprefix) == 1)            
  77.             {
  78.                 nob++;

  79. #ifdef _DEG
  80.                 printf("%s%s\n",bindir,DirEntry->d_name);
  81. #endif
  82.                 char *tloop = new char[strlen(bindir) + strlen(DirEntry->d_name)+5];
  83.                 strcat(strcat(tloop,bindir),DirEntry->d_name); //bindir like /test/test/test/ last / is must
  84.                 ins_chan(DirEntry->d_name,bindir,tloop,myq);
  85.                 delete [] tloop;
  86.             }
  87.         }
  88.         closedir(Dir);
  89.         if(nob == 0)
  90.         {
  91.             printf("WARNING:No Bin Log Find!!\n");
  92.             delete myq;
  93.             exit(12);
  94.         }
  95.     }
  96.     frs_nd = myq->first;
  97.     delete myq;
  98.     return frs_nd;
  99. }

  100. uint checkbin(const char* file_name,const char* binprefix)
  101. {
  102.     uint lenprefix = strlen(binprefix); //exp 5
  103.     uint filelen = strlen(file_name);
  104.     uint i;
  105.     uint t;
  106.     char tmpfix[strlen(binprefix)+1]; //exp strlen(binprefix)+1 =6
  107.     memset(tmpfix,0,strlen(binprefix)+1);
  108.     for(i=0;i<=lenprefix-1;i++) //exp lenprefix-1=4
  109.     {
  110.         tmpfix[i]=file_name[i]; //5 char copy tmpfix[0-4]
  111.     }
  112.     tmpfix[lenprefix]='\0'; //tmpfix[5] = '\0'
  113. #ifdef _DEG
  114.     cout<<"PROCESS:Checkbin Binlogprefix: "<<tmpfix<<endl;
  115. #endif
  116.     if(!strcmp(tmpfix,binprefix)) //check prefix eq tmpfix
  117.     {
  118.         for(t=(filelen-1);t>=(filelen-6);t--) //exp filelen-1=10 filelen-6=5
  119.         {
  120.             if(file_name[t]<48 || file_name[t]>57 ) //check 000000
  121.             {
  122.                 return 0;
  123.             }
  124.         }
  125.         if(file_name[filelen-7] !='.') //check . of .000000
  126.         {
  127.             return 0;
  128.         }
  129.     }
  130.     else
  131.     {
  132.         return 0;
  133.     }
  134.     return 1;
  135. }

  136. void show( F_NODE* const frs_nd)
  137. {
  138.     F_NODE* scan_nd = frs_nd;
  139.     do {
  140.         if(!scan_nd->next)
  141.         {
  142.             break;
  143.         }
  144.         printf("INFO:%s,%s,%s,%lu,%u\n",scan_nd->data->file_name,scan_nd->data->path_name,scan_nd->data->full_name,scan_nd->data->file_st,scan_nd->data->nuse);
  145.         scan_nd = scan_nd->next;
  146.     } while(scan_nd->next);
  147.     printf("INFO:%s,%s,%s,%lu,%u\n",scan_nd->data->file_name,scan_nd->data->path_name,scan_nd->data->full_name,scan_nd->data->file_st,scan_nd->data->nuse);
  148. }



  149. ulong char_to_num(const char* file_name)
  150. {
  151.     uint len = strlen(file_name);
  152.     uint i;
  153.     ulong num=0;
  154.     uint chk=0;

  155.     for(i=(len-1);i>0;i--)
  156.     {
  157.         if(file_name[i]>=48 && file_name[i]<=57)
  158.         {
  159.             num = (ulong)(file_name[i] - 48)*(ulong)pow(10,chk)+num;
  160.             chk++;
  161.         }
  162.     }
  163.     return num;
  164. }


  165. void time_to_time(char* ltime,char* mytime)
  166. {
  167.     char buffer[10];
  168.     buffer[0] = ltime[4];
  169.     buffer[1] = ltime[5];
  170.     buffer[2] = ltime[6];
  171.     buffer[3] = '\0';

  172.     mytime[0]=ltime[20];
  173.     mytime[1]=ltime[21];
  174.     mytime[2]=ltime[22];
  175.     mytime[3]=ltime[23];
  176.     if(!strcmp(buffer,"Jan"))
  177.     {

  178.         mytime[4]='0';
  179.         mytime[5]='1';
  180.     }
  181.     if(!strcmp(buffer,"Feb"))
  182.     {

  183.         mytime[4]='0';
  184.         mytime[5]='2';
  185.     }
  186.     if(!strcmp(buffer,"Mar"))
  187.     {

  188.         mytime[4]='0';
  189.         mytime[5]='3';
  190.     }
  191.     if(!strcmp(buffer,"Apr"))
  192.     {

  193.         mytime[4]='0';
  194.         mytime[5]='4';
  195.     }
  196.     if(!strcmp(buffer,"May"))
  197.     {

  198.         mytime[4]='0';
  199.         mytime[5]='5';
  200.     }
  201.     if(!strcmp(buffer,"Jun"))
  202.     {

  203.         mytime[4]='0';
  204.         mytime[5]='6';
  205.     }
  206.     if(!strcmp(buffer,"Jul"))
  207.     {

  208.         mytime[4]='0';
  209.         mytime[5]='7';
  210.     }
  211.     if(!strcmp(buffer,"Aug"))
  212.     {

  213.         mytime[4]='0';
  214.         mytime[5]='8';
  215.     }
  216.     if(!strcmp(buffer,"Sep"))
  217.     {

  218.         mytime[4]='0';
  219.         mytime[5]='9';
  220.     }
  221.     if(!strcmp(buffer,"Oct"))
  222.     {

  223.         mytime[4]='1';
  224.         mytime[5]='0';
  225.     }
  226.     if(!strcmp(buffer,"Nov"))
  227.     {

  228.         mytime[4]='1';
  229.         mytime[5]='1';
  230.     }
  231.     if(!strcmp(buffer,"Dec"))
  232.     {

  233.         mytime[4]='1';
  234.         mytime[5]='2';
  235.     }

  236.     if(ltime[8]<48 ||ltime[8]>57)
  237.     {

  238.         mytime[6]=48;
  239.     }
  240.     else
  241.     {

  242.         mytime[6]=ltime[8];
  243.     }
  244.     mytime[7]=ltime[9];
  245.     mytime[8]='\0';
  246. }



  247. void ftp_script(const char* ftp_dir,F_NODE* frs_nd)
  248. {
  249.     time_t now;
  250.     F_NODE* scan_nd = frs_nd;
  251.     struct tm* nowtm;
  252.     FILE* ftp=0;
  253.     FILE* tmp=0;
  254.     char timebuf[40];
  255.     char mytime[25];
  256.     char myftpdir[1000];
  257.     char tmpdir[1000];
  258.     ulong tmp_max_st;
  259.     ulong max_st_1;
  260.     int i=0;
  261.     int freeno=0;

  262.     memset(timebuf,0,40);
  263.     memset(mytime,0,40);
  264.     time(&now);
  265.     nowtm = localtime(&now);
  266.     asctime_r(nowtm,timebuf);
  267.     time_to_time(timebuf,mytime);
  268. #ifdef _DEG
  269.     printf("INFO:Ftp_scirpt fun time:\n%s%s\n",timebuf,mytime);
  270. #endif
  271.     memset(myftpdir,0,1000);
  272.     if((ftp=fopen(strcat(strcat(myftpdir,ftp_dir),mytime),"w"))==NULL)
  273.     {

  274.         perror("ERROR(14):Ftpdir open error:");
  275.         freeno=myfree(frs_nd);
  276.         cout<<"PROCESS:Free Mem:Free Node Is:"<<freeno<<endl;
  277.         exit(14);
  278.     }
  279.     memset(tmpdir,0,1000);
  280.     if((tmp=fopen(strcat(strcat(tmpdir,ftp_dir),"tmp"),"r"))==NULL)
  281.     {
  282.         printf("ERROR(15):No Tmp File Found,Please Create it frist!\n");
  283.         freeno=myfree(frs_nd);
  284.         cout<<"PROCESS:Free Mem:Free Node Is:"<<freeno<<endl;
  285.         exit(15);
  286.     }
  287.     else
  288.     {
  289. #ifdef _DEG
  290.         printf("INFO:Ftp_scirpt Fun Tmpfile :%s\n",tmpdir);
  291. #endif
  292.         tmp_max_st=readtmp(tmp,tmpdir);    
  293.     }
  294.     memset(tmpdir,0,1000);
  295.     if((tmp=fopen(strcat(strcat(tmpdir,ftp_dir),"tmp"),"w"))==NULL)
  296.     {

  297.         printf("ERROR:Have No Write Privi In %s?\n",tmpdir);
  298.         perror("ERROR(18):Tmpfile Open W Error:");
  299.         freeno=myfree(frs_nd);
  300.         cout<<"PROCESS:Free Mem:Free Node Is:"<<freeno<<endl;
  301.         exit(18);
  302.     }
  303.     else
  304.     {
  305.         printf("INFO:Tmpfile Write Mode Succ!\n");
  306.     }

  307.     max_st_1 = get_max_st(frs_nd) - 1;
  308.     printf("INFO:Ftp_Scirpt Fun Tmp_max_st:%lu Max_st_1:%lu:\n",tmp_max_st,max_st_1);    
  309.     do{
  310.         if(!scan_nd->next)
  311.         {
  312.             break;
  313.         }
  314.         if(scan_nd->data->file_st > tmp_max_st && scan_nd->data->file_st <= max_st_1)
  315.         {
  316.             i++;
  317.             fputs("put ",ftp);
  318.             fputs(scan_nd->data->full_name,ftp);
  319.             fputs(" ",ftp);
  320.             fputs(scan_nd->data->file_name,ftp);
  321.             fputs("\n",ftp);
  322.         }
  323.         scan_nd = scan_nd->next;
  324.     }while(scan_nd->next);
  325.     if(scan_nd->data->file_st > tmp_max_st && scan_nd->data->file_st <= max_st_1)
  326.     {
  327.         i++;
  328.         fputs("put ",ftp);
  329.         fputs(scan_nd->data->full_name,ftp);
  330.         fputs(" ",ftp);
  331.         fputs(scan_nd->data->file_name,ftp);
  332.         fputs("\n",ftp);
  333.     }

  334.     printf("INFO:Scan Put Counter :%d\n",i);
  335.     if(i == 0)
  336.     {
  337.         printf("INFO:Read Max Binlog From Temp is :%lu\n",tmp_max_st);
  338.         fprintf(tmp,"%lu",tmp_max_st);
  339.         fputs("\n",tmp);
  340.     }
  341.     else
  342.     {
  343.         printf("INFO:Current Max Binlog-1 is:%lu\n",max_st_1);
  344.         fprintf(tmp,"%lu",max_st_1);
  345.         fputs("\n",tmp);
  346.     }

  347.     fclose(ftp);
  348.     fclose(tmp);
  349. }

  350. int get_max_st(F_NODE* const frs_nd)
  351. {
  352.     F_NODE* scan_nd = frs_nd;    
  353.     ulong max_st=0;
  354.     do {
  355.         if(!scan_nd->next)
  356.         {
  357.             break;
  358.         }
  359.         if(scan_nd->data->file_st > max_st)
  360.         {
  361.             max_st = scan_nd->data->file_st;
  362.         }
  363.         scan_nd = scan_nd->next;
  364.     }while(scan_nd->next);
  365.     if(scan_nd->data->file_st > max_st)
  366.     {
  367.         max_st = scan_nd->data->file_st;
  368.     }
  369.     return max_st;
  370. }




  371. ulong readtmp(FILE *fd,const char* tmpdir)
  372. {
  373.     struct stat buf;
  374.     ulong max_st = 0;

  375.     if(lstat(tmpdir, &buf) < 0)
  376.     {
  377.         perror("ERROR(16):Lstat Error:");
  378.         exit(16);
  379.     }
  380.     if(buf.st_size == 0)
  381.     {
  382.         max_st = 0;
  383.     }
  384.     else
  385.     {
  386.         fscanf(fd,"%lu",&max_st);
  387.         /*
  388.          if(max_st == 0)
  389.          {
  390.          printf("Tmp File Is Bad ?\n");
  391.          exit(17);
  392.          }
  393.          */
  394.     }
  395.     return max_st;
  396. }



  397. int myfree(F_NODE* const frs_nd)
  398. {

  399.     F_NODE* scan_nd = frs_nd;
  400.     F_NODE* cur_nd = 0;
  401.     int i = 0;
  402.     do{
  403.         cur_nd = scan_nd;
  404.         if(!scan_nd->next)
  405.         {
  406.             free(cur_nd->data->file_name);
  407.             free(cur_nd->data->path_name);
  408.             free(cur_nd->data->full_name);
  409.             free(cur_nd->data);
  410.             free(cur_nd);
  411.             i++;
  412.             return i;
  413.         }
  414.         scan_nd = scan_nd->next;
  415.         free(cur_nd->data->file_name);
  416.         free(cur_nd->data->path_name);
  417.         free(cur_nd->data->full_name);
  418.         free(cur_nd->data);
  419.         free(cur_nd);
  420.         i++;
  421.     }while(scan_nd->next);
  422.     free(scan_nd->data->file_name);
  423.     free(scan_nd->data->path_name);
  424.     free(scan_nd->data->full_name);
  425.     free(scan_nd->data);
  426.     free(scan_nd);
  427.     i++;
  428.     return i;
  429. }

  430. uint checkdir(const char* mychar)
  431. {
  432.     uint len = strlen(mychar);
  433.     if(mychar[len-1] == '/' )
  434.     {
  435.         return 0;
  436.     }
  437.     else
  438.     {
  439.         return 1;
  440.     }
  441. }


相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
打赏
0
0
0
0
91
分享
相关文章
图解MySQL【日志】——Redo Log
Redo Log(重做日志)是数据库中用于记录数据页修改的物理日志,确保事务的持久性和一致性。其主要作用包括崩溃恢复、提高性能和保证事务一致性。Redo Log 通过先写日志的方式,在内存中缓存修改操作,并在适当时候刷入磁盘,减少随机写入带来的性能损耗。WAL(Write-Ahead Logging)技术的核心思想是先将修改操作记录到日志文件中,再择机写入磁盘,从而实现高效且安全的数据持久化。Redo Log 的持久化过程涉及 Redo Log Buffer 和不同刷盘时机的控制参数(如 `innodb_flush_log_at_trx_commit`),以平衡性能与数据安全性。
26 5
图解MySQL【日志】——Redo Log
MySQL日志详解——日志分类、二进制日志bin log、回滚日志undo log、重做日志redo log
MySQL日志详解——日志分类、二进制日志bin log、回滚日志undo log、重做日志redo log、原理、写入过程;binlog与redolog区别、update语句的执行流程、两阶段提交、主从复制、三种日志的使用场景;查询日志、慢查询日志、错误日志等其他几类日志
101 35
MySQL日志详解——日志分类、二进制日志bin log、回滚日志undo log、重做日志redo log
图解MySQL【日志】——两阶段提交
两阶段提交是为了解决Redo Log和Binlog日志在事务提交时可能出现的半成功状态,确保两者的一致性。它分为准备阶段和提交阶段,通过协调者和参与者协作完成。准备阶段中,协调者向所有参与者发送准备请求,参与者执行事务并回复是否同意提交;提交阶段中,若所有参与者同意,则协调者发送提交请求,否则发送回滚请求。MySQL通过这种方式保证了分布式事务的一致性,并引入组提交机制减少磁盘I/O次数,提升性能。
27 4
图解MySQL【日志】——两阶段提交
MySQL原理简介—7.redo日志的底层原理
本文介绍了MySQL中redo日志和undo日志的主要内容: 1. redo日志的意义:确保事务提交后数据不丢失,通过记录修改操作并在系统宕机后重做日志恢复数据。 2. redo日志文件构成:记录表空间号、数据页号、偏移量及修改内容。 3. redo日志写入机制:redo日志先写入Redo Log Buffer,再批量刷入磁盘文件,减少随机写以提高性能。 4. Redo Log Buffer解析:描述Redo Log Buffer的内存结构及刷盘时机,如事务提交、Buffer过半或后台线程定时刷新。 5. undo日志原理:用于事务回滚,记录插入、删除和更新前的数据状态,确保事务可完整回滚。
109 22
MySQL日志
本文介绍了MySQL中三个重要的日志:binlog、redolog和undolog。binlog记录数据库更改操作,支持数据恢复、复制和审计;redolog保证事务的原子性和持久性,实现crash-safe;undolog用于事务回滚及MVCC的实现。每个日志都有其独特的作用和应用场景,确保数据库的稳定性和数据一致性。
图解MySQL【日志】——磁盘 I/O 次数过高时优化的办法
当 MySQL 磁盘 I/O 次数过高时,可通过调整参数优化。控制刷盘时机以降低频率:组提交参数 `binlog_group_commit_sync_delay` 和 `binlog_group_commit_sync_no_delay_count` 调整等待时间和事务数量;`sync_binlog=N` 设置 write 和 fsync 频率,`innodb_flush_log_at_trx_commit=2` 使提交时只写入 Redo Log 文件,由 OS 择机持久化,但两者在 OS 崩溃时有丢失数据风险。
25 3
图解MySQL【日志】——Buffer Pool
Buffer Pool 是数据库管理系统(DBMS)中用于缓存磁盘数据页的内存区域,主要包含数据页、索引页、undo 页等。它通过减少磁盘 I/O 提升性能,特别是在处理大型数据库时效果显著。查询时,整个数据页而非单条记录会被加载到 Buffer Pool 中,以提高访问效率。
17 0
图解MySQL【日志】——Buffer Pool
Mysql、Oracle审计日志的开启
通过上述步骤,可以在 MySQL 和 Oracle 数据库中启用和配置审计日志。这些日志对于监控数据库操作、提高安全性和满足合规性要求非常重要。确保正确配置审计参数和策略,定期查看和分析审计日志,有助于及时发现并处理潜在的安全问题。
76 11
MySQL事务日志-Undo Log工作原理分析
事务的持久性是交由Redo Log来保证,原子性则是交由Undo Log来保证。如果事务中的SQL执行到一半出现错误,需要把前面已经执行过的SQL撤销以达到原子性的目的,这个过程也叫做"回滚",所以Undo Log也叫回滚日志。
107 7
MySQL事务日志-Undo Log工作原理分析
图解MySQL【日志】——Undo Log
Undo Log(回滚日志)是 MySQL 中用于实现事务原子性和一致性的关键机制。在默认的自动提交模式下,MySQL 隐式开启事务,每条增删改语句都会记录到 Undo Log 中。其主要作用包括:
25 0