十年網(wǎng)站開發(fā)經(jīng)驗 + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊
量身定制 + 運營維護(hù)+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
目的:本篇是自己用C++實現(xiàn)的ddl的簡單腳本(改寫自自己的shell,但是還有一部分沒完成),用來鍛煉自己寫C++的能力
網(wǎng)站建設(shè)、網(wǎng)站制作,成都做網(wǎng)站公司-成都創(chuàng)新互聯(lián)公司已向超過千家企業(yè)提供了,網(wǎng)站設(shè)計,網(wǎng)站制作,網(wǎng)絡(luò)營銷等服務(wù)!設(shè)計與技術(shù)結(jié)合,多年網(wǎng)站推廣經(jīng)驗,合理的價格為您打造企業(yè)品質(zhì)網(wǎng)站。
頭文件exec_ddl.h
```
#include
#include
#include
#include
#include
size_t GetStrCurrTime(std::string &);
#ifndef header_cpp_fun_h
#define header_cpp_fun_h
class CDdlGhost {
private:
//數(shù)據(jù)庫賬號,端口,DDL用戶,密碼,
std::string host;
int port;
std::string user;
std::string password;
std::string database;
std::string tableName;
int threadRunning = 500;
int cthreadRunning = 500;
int maxLagMillis = 3000;
std::string cutOver = "default";
int chunkSize = 1000;
int lockSeconds = 60;
int retries = 3;
static CDdlGhost* instance;
CDdlGhost(std::string host,int port,std::string database,std::string tableName,std::string user,std::string password);
public:
static CDdlGhost* GetSingleInstance(std::string host,int port,std::string database,std::string tableName,std::string user,std::string password);
int GetGhostCmd(std::string sql,std::string &cmd);
int ExecDdlCmd(std::string &cmd);
};
#endif
```
exec_ddl.cpp
```
#include "exec_ddl.h"
//類中靜態(tài)變量為什么不在類中初始化,是因為靜態(tài)變量具有外部鏈接性,文件作用域
CDdlGhost* CDdlGhost::instance = nullptr;
//構(gòu)造函數(shù)
CDdlGhost::CDdlGhost(std::string host,int port,std::string database,std::string tableName,std::string user,std::string password){
//這里以后正則表達(dá)式做安全性過濾
this->host = host;
this->port = port;
this->database = database;
this->tableName = tableName;
this->user = user;
this->password = password;
}
//獲取類的單實例函數(shù),這里為什么返回的是指針而不是引用是因為我要用空指針才判斷是否單實例
CDdlGhost* CDdlGhost::GetSingleInstance(std::string host,int port,std::string database,std::string tableName,std::string user,std::string password){
if(nullptr == instance){
instance = new CDdlGhost(host,port,database,tableName,user,password);
}
return instance;
}
//獲得表結(jié)構(gòu)更改的命令字符串
int CDdlGhost::GetGhostCmd(std::string sql,std::string &ghostCmd){
//獲取環(huán)境變量
const char* pathEnv = std::getenv("PATH");
std::string ghostLog;
//這個變量用來獲取當(dāng)前時間戳
std::string strTime;
size_t ret = GetStrCurrTime(strTime);
if(ret <= 0){
std::cout<<"獲取當(dāng)前時間戳失敗"<
}
ghostLog=ghostLog+"/data1/upload/ghost_"+tableName+"_"+strTime+".log";
ghostCmd="gh-ost --ok-to-drop-table --initially-drop-ghost-table --skip-foreign-key-checks --allow-on-master --switch-to-rbr --allow-master-master --exact-rowcount --verbose --initially-drop-old-table ";
ghostCmd=ghostCmd + "--max-load=Threads_running="+std::to_string(threadRunning)+" --critical-load=Threads_running="+std::to_string(cthreadRunning)+" --chunk-size="+std::to_string(chunkSize)+" --cut-over="+cutOver+" --max-lag-millis="+std::to_string(maxLagMillis)+" --cut-over-lock-timeout-seconds="+std::to_string(lockSeconds)+" --default-retries="+std::to_string(retries)+" --host=\'"+host+"' --user='"+user+"' --password='"+password+"' --database='"+database+"' --table='"+tableName+"' --alter='"+sql+"' --panic-flag-file=/tmp/"+tableName+".ghost.panic.flag --execute > "+ghostLog+" 2>&1";
return 1;
/*
if(execl("/bin/sh","sh","-c",ghostCmd.c_str(),(char *) 0)<0){
std::cout<<"執(zhí)行g(shù)hostCmd失敗,語句為:"<
}
*/
}
int CDdlGhost::ExecDdlCmd(std::string &ghostCmd){
pid_t pidGhost;
int GhostStatus;
//這里我還要fork一個掃描ghost產(chǎn)生的日志的子進(jìn)程,但是現(xiàn)在暫時沒打開
//pid_t pidScan;
if((pidGhost = fork()) < 0){
std::cout<<"pidGhost子進(jìn)程fork失敗"<
}
/*
if((pidScan = fork()) < 0){
std::cout<<"pidScan子進(jìn)程fork失敗"<
}
*/
//子進(jìn)程要執(zhí)行修改表結(jié)構(gòu)命令了
if(0 == pidGhost){
//為什么不用system,因為不想子進(jìn)程fork子進(jìn)程
if(execl("/bin/sh","sh","-c",ghostCmd.c_str(),(char *) 0)<0){
std::cout<<"臥槽,執(zhí)行命令失敗了"<
}
_exit(127);
}
//另一個子進(jìn)程,每一秒檢查下日志文件,看看是否有鎖,有鎖就kill,暫時沒啟用
/*
if(0 == pidScan ){
while(1){
int ret = ScanGhostLogLock(std::string &ghostLog);
if(ret > 0){
KillSleepOrLongQuery();
}
sleep(1);
}
*/
/*這里后面會通過一個函數(shù)掃描子進(jìn)程執(zhí)行的命令的日志,執(zhí)行完后通知父進(jìn)程*/
//等待子進(jìn)程結(jié)束
if(waitpid(pidGhost,&GhostStatus,0) < 0){
std::cout<<"等待子進(jìn)程出現(xiàn)異常"<
}
/*這里以后會通過函數(shù)向后臺掃描日志進(jìn)程發(fā)送信號,通知其結(jié)束*/
if(WIFEXITED(GhostStatus)){
return 0;
}
return -3;
}
//獲取格式化后的日期字符串
size_t GetStrCurrTime(std::string &strTime){
time_t now = time(NULL);
struct tm timeinfo = *localtime(&now);
char buf[30];
size_t ret = strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", &timeinfo);
std::string str(buf);
strTime = str;
return ret;
}
```
ddl_main.cpp
```
#include
#include "exec_ddl.h"
int main(){
int i=0,ret;
CDdlGhost *pDdlGhost=CDdlGhost::GetSingleInstance("10.17.4.23",3306,"test","test1","zaixinyuan","test123456");
if (pDdlGhost == nullptr){
std::cout<<"分配對象內(nèi)存失敗"<
}
std::string ghostCmd;
i = pDdlGhost->GetGhostCmd("add index cname(c)",ghostCmd);
ret = pDdlGhost->ExecDdlCmd(ghostCmd);
std::cout<<"返回結(jié)果是:"< if(ret <0){
std::cout<<"更改表結(jié)構(gòu)失敗"<
delete pDdlGhost;
}
```
編譯命令
```
g++ -std=gnu++11 -o ddl_ghost ddl_main.cpp exec_ddl.cpp
```
執(zhí)行結(jié)果:
程序返回結(jié)果
數(shù)據(jù)庫查看結(jié)果