python連接資料庫集群進行自動化運維

之前的文章中介紹了python連接mysql,teradata,DB2資料庫。我們學會了python如何連接這些資料庫,並進行簡單的增刪改查。

現在實際工作中遇到這樣的場景:開發人員在開發環境建好了表(準備好了建表語句等腳本),需要在生產環境統一建表;隨著業務的增加,資料庫越來越多,擴展到了幾十個至近百個mysql集群。

這個時候像原來打開mysql客戶端,一個一個的執行SQL語句就比較機械和繁瑣了;而且由於資料庫名和相似,很容易看花眼建錯地方。此時,通過Python自動化解析建表語句,自動選擇對應的mysql資料庫,連接後執行,豈不完美。

為此要實現:

  • + 建立集群信息配置表
  • + 自動解析SQL語句及對應庫名
  • + 連接資料庫後執行

1.配置表信息

連接資料庫需要實例名,主機IP,用戶名,和密碼。將這些信息存儲在如下樣例表中。並且實例名db_name不重複。每次連接mysql資料庫,都需要解析這些表中信息用來連接資料庫。

實際使用中,上述表保存在csv文件中。程序開始時讀取,放在一個字典里,資料庫實例名作為主鍵。

db_ctl_file = csv.reader(open(.mysql_clt_ini.csv)) ndb_dict = {} nfor row in islice(db_ctl_file,1,None): #通過islice函數跳過第一行標題ntdb_dict[row[0]]=row[1:] n

2.解析SQL語句

SQL語句放在文件中,語言和語句之間用分號`;`分割。文件名和實例名有關,比如文件名`xxx012.sql`,表示兩個實例:

  • xxx01
  • xxx02

共享此文件中SQL語句。(一般都有主備庫成對出現)

文件名`xxx01256.sql`,表示實例

  • xxx01
  • xxx02
  • xxx05
  • xxx06

都需要執行此文件下的SQL語句。以此類推。

由於不能一次執行多條SQL語句,需要對SQL語句進行逐一提取,放在一個列表中。

定義函數如下:

```

def fetch_sql_dll(filelist= []): ntsql_dict = {} ntfor file_name in filelist: nttprint file_name nttfile_text = open(./ddl/+file_name,r) nttsql_text = [] #初始化SQL語句列表,一個文件中有多個sql語句nttsql = #初始化單條SQL語句nttfor line in file_text: ntttsql = sql+ line ntttif line.find(;) <> -1: ntttt#本行有分號;說明這一行是本條SQL語句最後一行ntttt#append初始化下一個SQL語句nttttsql_text.append(sql) nttttsql = nttfile_text.close() nnttdb_str = file_name.split(.)[0] #去掉文件名後綴nttfor db_i in db_str.split(0)[-1]: nttntttdb_name = db_str.split(0)[0]+0+db_i nttt#拼接資料庫實例名ntttprint db_name ntttsql_dict[db_name] = sql_text nttt#print sql_len ,len(sql_text) ntntreturn sql_dict n

```

函數的輸入是保存SQL的文件名列表,輸出是資料庫實例名對應建表語句的字典。

3.連接mysql並執行SQL語句

這裡定義一個函數,傳入mysql連接信息,及需要在這個mysql庫中執行的SQL語句列表。

```

def connect_mysql(con_str,sqls= None): ntconn = MySQLdb.connect( nttthost = con_str[1], ntttport = 3306, ntttuser = con_str[2], ntttpasswd = con_str[3], ntttdb = con_str[0]) tnttry:tnttcur = conn.cursor() tnttfor sql in sqls: ntttcur.execute(sql) nttprint %s connect ok!%con_str[0]nttcur.close() nttconn.commit() nttconn.close() ntexcept: nttptinr(connect error !) n

```

連接之後,循環執行SQL語句。放在`try-except`語句中防止異常出現。

4.完整代碼

首先導入需要的庫;兩個函數定義同上;main函數中列出所有SQL文件,循環執行上述流程。

import os nimport csv nimport MySQLdb nfrom itertools import islice nndb_ctl_file = csv.reader(open(.mysql_clt_ini.csv)) ndb_dict = {} nfor row in islice(db_ctl_file,1,None): ntdb_dict[row[0]]=row[1:] nndef fetch_sql_dll(filelist= []): ntsql_dict = {} ntfor file_name in filelist: nttprint file_name nttfile_text = open(./ddl/+file_name,r) nttsql_text = [] nttsql = nttfor line in file_text: ntttsql = sql+ line ntttif line.find(;) <> -1: ntttt#本行有;說明這一行是本條SQL語句最後一行ntttt#append加入後初始化下一個SQL語句nttttsql_text.append(sql) nttttsql = nttnttfile_text.close() nttnttdb_str = file_name.split(.)[0] #去掉文件名後綴nttfor db_i in db_str.split(0)[-1]: nttntttdb_name = db_str.split(0)[0]+0+db_i nttt#拼接資料庫實例名ntttprint db_name ntttsql_dict[db_name] = sql_text nttt#print sql_len ,len(sql_text) ntreturn sql_dict nndef connect_mysql(con_str,sqls= None): ntconn = MySQLdb.connect( nttthost = con_str[1],ntttport = 3306, ntttuser = con_str[2], ntttpasswd = con_str[3], ntttdb = con_str[0])nttry:nttcur = conn.cursor() nttfor sql in sqls: ntttcur.execute(sql) nttprint connect ok! nttcur.close() nttconn.commit() nttconn.close() ntexcept: nttptinr(connect error !) nttnif __name__ == "__main__": ntfilelist = os.listdir(.ddl) #列出文件夾下所有SQL文件ntsql_dict = {} ntsql_dict = fetch_sql_dll(filelist) ntntfor db_nm,sqls in sql_dict.items(): nttprint db_nm nttif db_nm in db_dict.keys(): ntttcon_str = (db_nm,db_dict[db_nm][0],db_dict[db_nm][1],db_dict[db_nm][2]) ntttconnect_mysql(con_str, sqls) ntelse: nttprint db_nm,"not find in db_dict!"n

好了,腳本準備好了,每次一行命令就可以了。剩下的時間干點有意義的事情,比如刷手機,坐等執行完成。

先實現自動化,才能進一步實現智能化。

公眾號DataCode首發,歡迎關注。

weixin.qq.com/r/Ti5eRv- (二維碼自動識別)


推薦閱讀:

可以用 Python 來幹些什麼有趣的事?
python buildin 中的一些類中為什麼方法的內容都是pass?
uWSGI 伺服器的 uwsgi 協議究竟用在何處?

TAG:Python | 数据库 | 运维自动化 |