diff_mysql_table

#!/usr/bin/env python

#-*- encoding: utf8 -*-

import mysql.connector

# 定義要導(dǎo)出文件目錄

work_dir="/data/python/"

class DiffTable:

# fromdbconfig 參數(shù)是一個(gè)列表,是源端數(shù)據(jù)庫(kù)能耻, todbconfig 參數(shù)也是一個(gè)列表,是目標(biāo)端數(shù)據(jù)庫(kù)(也就是要修改的數(shù)據(jù)庫(kù))乍迄,第一列是IP,第二列是DB砾隅,第三列是賬號(hào)锅移,第四列是密碼,第五列是端口號(hào)释移。

def __init__(self, fromdbconfig,todbconfig):

self.fromdbconfig = fromdbconfig

self.todbconfig = todbconfig

# 獲取源端數(shù)據(jù)庫(kù)表名,輸出結(jié)果為列表

def get_source_table_name(self):

select_tables_sql = "select table_name from information_schema.tables where table_schema='%s' order by table_name;" %(self.fromdbconfig[1])

cnn = mysql.connector.connect(host=self.fromdbconfig[0], db=self.fromdbconfig[1], user=self.fromdbconfig[2], password=self.fromdbconfig[3],port=self.fromdbconfig[4])

cursor = cnn.cursor()

cursor.execute(select_tables_sql)

source_table_result = cursor.fetchall()

return source_table_result

# 獲取目標(biāo)端源端數(shù)據(jù)庫(kù)表名寥殖,輸出結(jié)果為列表

def get_target_table_name(self):

select_tables_sql = "select table_name from information_schema.tables where table_schema='%s' order by table_name;" %(self.todbconfig[1])

cnn = mysql.connector.connect(host=self.todbconfig[0], db=self.todbconfig[1], user=self.todbconfig[2], password=self.todbconfig[3],port=self.todbconfig[4])

cursor = cnn.cursor()

cursor.execute(select_tables_sql)

target_table_result = cursor.fetchall()

return target_table_result

# 獲取指定數(shù)據(jù)庫(kù)source_list 里面存在玩讳,但是target_list不存在的對(duì)象,獲取這些表嚼贡,用于生成create table 語(yǔ)句熏纯。

def get_create_table_list(self):

create_table_ret_list = []

for i in range(len(self.get_source_table_name())):

if self.get_source_table_name()[i] not in self.get_target_table_name():

create_table_ret_list.append(self.get_source_table_name()[i])

return create_table_ret_list

# 獲取指定數(shù)據(jù)庫(kù)source_list 里面存在,但是 get_create_table_list 不存在的對(duì)象粤策,獲取這些表樟澜,用于生成alter table? 語(yǔ)句。

def get_alter_table_list(self):

alter_table_ret_list = []

for i in range(len(self.get_source_table_name())):

if self.get_source_table_name()[i] in self.get_target_table_name():

alter_table_ret_list.append(self.get_source_table_name()[i])

return alter_table_ret_list

# 獲取數(shù)據(jù)庫(kù)表的create table 信息叮盘,輸出結(jié)果為字典秩贰,表名是key,對(duì)應(yīng)表create table語(yǔ)句為 value 柔吼,用于創(chuàng)建目標(biāo)端沒(méi)有的表毒费。

def generate_create_statement(self):

from_table_name_list = []

from_table_name_dict = {}

cnn = mysql.connector.connect(host=self.fromdbconfig[0], db=self.fromdbconfig[1], user=self.fromdbconfig[2], password=self.fromdbconfig[3],port=self.fromdbconfig[4])

cursor = cnn.cursor()

for item in range(len(self.get_create_table_list())):

show_create_table_sql = "show create table %s;" % (self.get_create_table_list()[item][0])

cursor.execute(show_create_table_sql)

result = cursor.fetchall()

from_table_name_list.append(result)

for i in from_table_name_list:

from_table_name_dict[i[0][0]] = i[0][1]+i[0][1].join(';')

return from_table_name_dict

# 獲取源端數(shù)據(jù)庫(kù)表信息,輸出結(jié)果為字典愈魏,表名為key觅玻,表信息為value想际,用于后續(xù)對(duì)比源端和目標(biāo)端表結(jié)構(gòu)是否異同。

def get_source_column_info(self):

source_table_name_list = []

source_ret_dict = {}

cnn = mysql.connector.connect(host=self.fromdbconfig[0], db=self.fromdbconfig[1], user=self.fromdbconfig[2], password=self.fromdbconfig[3],port=self.fromdbconfig[4])

cursor = cnn.cursor()

for item in range(len(self.get_alter_table_list())):

select_columns_sql = "select TABLE_NAME,COLUMN_NAME,COLUMN_TYPE,COLUMN_DEFAULT,COLUMN_COMMENT from information_schema.columns where table_schema='%s' and table_name='%s' order by table_name;" %(self.fromdbconfig[1],self.get_alter_table_list()[item][0])

cursor.execute(select_columns_sql)

result = cursor.fetchall()

source_table_name_list.append(result)

for i in range(len(source_table_name_list)):

source_ret_dict[source_table_name_list[i][0][0]] = source_table_name_list[i]

return source_ret_dict

# 獲取目標(biāo)數(shù)據(jù)庫(kù)表信息溪厘,輸出結(jié)果為字典胡本,表名為key,表信息為value桩匪,用于后續(xù)對(duì)比源端和目標(biāo)端表結(jié)構(gòu)是否異同打瘪。

def get_target_column_info(self):

target_table_name_list = []

target_ret_dict = {}

target_null_list = []

cnn = mysql.connector.connect(host=self.todbconfig[0], db=self.todbconfig[1], user=self.todbconfig[2], password=self.todbconfig[3],port=self.todbconfig[4])

cursor = cnn.cursor()

for item in range(len(self.get_alter_table_list())):

select_columns_sql = "select TABLE_NAME,COLUMN_NAME,COLUMN_TYPE,COLUMN_DEFAULT,COLUMN_COMMENT from information_schema.columns where table_schema='%s' and table_name='%s' order by table_name;" %(self.fromdbconfig[1],self.get_alter_table_list()[item][0])

cursor.execute(select_columns_sql)

result = cursor.fetchall()

target_table_name_list.append(result)

while target_null_list in target_table_name_list:

target_table_name_list.remove(target_null_list)

for i in range(len(target_table_name_list)):

target_ret_dict[target_table_name_list[i][0][0]] = target_table_name_list[i]

return target_ret_dict

# 從 get_source_column_info 函數(shù)和 get_target_column_info 函數(shù)獲取結(jié)果集,比較兩邊表傻昙,得出差異的部分,后續(xù)再對(duì)此部分進(jìn)行生成alter table語(yǔ)句彩扔。

def generate_alter_statement(self):

source_column_list = []

source_alter_table_midify = []

source_alter_table_add = []

alter_statement_dict = {}

alter_statement_all = {}

alter_statement_modify = []

alter_statement_add = []

for key,value in self.get_source_column_info().viewitems():

for i in self.get_source_column_info()[key]:

for j in self.get_target_column_info()[key]:

if j[1] not in source_column_list:

source_column_list.append(j[1])

if i[0] == j[0]:

if i[1] == j[1]:

if i[2] == j[2] and i[3] == j[3] and i[4] == j[4]:

pass

else:

# 這部分?jǐn)?shù)據(jù)用于生成 alter table modify 語(yǔ)句

if i not in source_alter_table_midify:

source_alter_table_midify.append(i)

else:

# 這部分?jǐn)?shù)據(jù)用于生成 alter table add 語(yǔ)句

if i[1] not in source_column_list:

if i not in source_alter_table_add:

source_alter_table_add.append(i)

for i in range(len(source_alter_table_midify)):

alter_statement_modify.append("alter table? %s modify %s %s DEFAULT '%s' COMMENT '%s';" %(source_alter_table_midify[i][0],source_alter_table_midify[i][1],source_alter_table_midify[i][2],source_alter_table_midify[i][3],source_alter_table_midify[i][4]))

for i in range(len(source_alter_table_add)):

alter_statement_add.append("alter table? %s add %s %s DEFAULT '%s' COMMENT '%s';" %(source_alter_table_add[i][0],source_alter_table_add[i][1],source_alter_table_add[i][2],source_alter_table_add[i][3],source_alter_table_add[i][4]))

alter_statement_all['alter_modify'] = alter_statement_modify

alter_statement_all['alter_add'] = alter_statement_add

return alter_statement_all

# 此函數(shù)用來(lái)打印輸出SQL文件

def out_result(create_table_dict,alter_table_dict):

def print_result(table_dict,sql_name):

sql_file = work_dir+'sql_'+sql_name+'_diff_mysql'+'.sql'

with open(sql_file,"aw") as f:

f.write(table_dict+"\n")

for key,value in create_table_dict.viewitems():

print_result(create_table_dict[key],"create_table")

for key,value in alter_table_dict.viewitems():

for i in range(len(alter_table_dict[key])):

print_result(alter_table_dict[key][i],"alter_table")

fromdbconfig_105 = ['192.168.56.105', 'liangdb', 'root', '123456', '3306']

todbconfig_106 = ['192.168.56.106', 'liangdb', 'root', '123456', '3306']

alter_table_result = DiffTable(fromdbconfig_105,todbconfig_106).generate_create_statement()

create_table_result = DiffTable(fromdbconfig_105,todbconfig_106).generate_alter_statement()

print_sql = (alter_table_result,create_table_result)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末妆档,一起剝皮案震驚了整個(gè)濱河市言津,隨后出現(xiàn)的幾起案子入篮,更是在濱河造成了極大的恐慌,老刑警劉巖匿沛,帶你破解...
    沈念sama閱讀 212,657評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件敦捧,死亡現(xiàn)場(chǎng)離奇詭異须板,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)兢卵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,662評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門习瑰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人秽荤,你說(shuō)我怎么就攤上這事甜奄。” “怎么了窃款?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,143評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵课兄,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我晨继,道長(zhǎng)烟阐,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,732評(píng)論 1 284
  • 正文 為了忘掉前任紊扬,我火速辦了婚禮蜒茄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘珠月。我一直安慰自己扩淀,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,837評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布啤挎。 她就那樣靜靜地躺著驻谆,像睡著了一般卵凑。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上胜臊,一...
    開(kāi)封第一講書(shū)人閱讀 50,036評(píng)論 1 291
  • 那天勺卢,我揣著相機(jī)與錄音,去河邊找鬼象对。 笑死黑忱,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的勒魔。 我是一名探鬼主播甫煞,決...
    沈念sama閱讀 39,126評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼冠绢!你這毒婦竟也來(lái)了抚吠?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,868評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤弟胀,失蹤者是張志新(化名)和其女友劉穎楷力,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體孵户,經(jīng)...
    沈念sama閱讀 44,315評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡萧朝,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,641評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了夏哭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片检柬。...
    茶點(diǎn)故事閱讀 38,773評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖方庭,靈堂內(nèi)的尸體忽然破棺而出厕吉,到底是詐尸還是另有隱情,我是刑警寧澤械念,帶...
    沈念sama閱讀 34,470評(píng)論 4 333
  • 正文 年R本政府宣布头朱,位于F島的核電站,受9級(jí)特大地震影響龄减,放射性物質(zhì)發(fā)生泄漏项钮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,126評(píng)論 3 317
  • 文/蒙蒙 一希停、第九天 我趴在偏房一處隱蔽的房頂上張望烁巫。 院中可真熱鬧,春花似錦宠能、人聲如沸亚隙。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,859評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)阿弃。三九已至诊霹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間渣淳,已是汗流浹背脾还。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,095評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留入愧,地道東北人鄙漏。 一個(gè)月前我還...
    沈念sama閱讀 46,584評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像棺蛛,于是被迫代替她去往敵國(guó)和親怔蚌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,676評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容