当前位置: 首页 > news >正文

Python 助力 DBA:高效批量管理数据库服务器的多线程解决方案-多库查询汇总工具实现

批量数据库服务器连接测试与数据汇总:Python实现方案

作为数据库服务器运维人员,我们经常需要面对大量服务器的连接测试和数据汇总工作。本文将介绍一个使用Python实现的高效解决方案,可以帮助我们快速完成这些任务。

需求概述

  1. 从配置文件中读取要测试的数据库服务器IP地址列表。
  2. 批量测试数据库服务器的连接情况。
  3. 在所有可连接的服务器上执行相同的SQL查询。
  4. 将查询结果汇总到一个单独的数据库中,并包含对应服务器的IP地址。
  5. 自动创建结果表,表名按日期随机生成。
  6. 提供详细的日志输出,包括实时的处理进度。

实现方案

我们使用Python来实现这个方案,主要利用了以下库和技术:

  • pyodbc: 用于数据库连接和操作
  • configparser: 读取配置文件
  • concurrent.futures: 实现并发处理
  • logging: 日志记录
  • 多线程技术:提高处理效率

代码实现

以下是完整的Python代码实现:

import pyodbc
import logging
import configparser
from concurrent.futures import ThreadPoolExecutor, as_completed
import time
from datetime import datetime
import random
import string# 配置日志
def setup_logger():"""设置日志记录器,同时输出到文件和控制台"""logger = logging.getLogger()logger.setLevel(logging.INFO)# 文件处理器file_handler = logging.FileHandler('db_query_aggregation.log')file_handler.setLevel(logging.INFO)file_formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')file_handler.setFormatter(file_formatter)# 控制台处理器console_handler = logging.StreamHandler()console_handler.setLevel(logging.INFO)console_formatter = logging.Formatter('%(message)s')console_handler.setFormatter(console_formatter)logger.addHandler(file_handler)logger.addHandler(console_handler)return loggerlogger = setup_logger()def read_config(config_file):"""读取配置文件:param config_file: 配置文件路径:return: 包含配置信息的字典"""try:config = configparser.ConfigParser()config.read(config_file)return {'ip_list_file': config['Files']['ip_list_file'],'source_db_username': config['SourceDB']['username'],'source_db_password': config['SourceDB']['password'],'target_db_info': dict(config['TargetDB']),'max_workers': int(config['Settings']['max_workers']),'query': config['Query']['sql']}except Exception as e:logger.error(f"读取配置文件时出错: {e}")raisedef read_ip_list(file_path):"""从文件中读取IP地址列表:param file_path: IP地址文件路径:return: IP地址列表"""try:with open(file_path, 'r') as file:return [line.strip() for line in file if line.strip()]except IOError as e:logger.error(f"无法读取IP地址文件: {e}")return []def create_connection(server, database, username, password):"""创建数据库连接:param server: 服务器地址:param database: 数据库名称:param username: 用户名:param password: 密码:return: 数据库连接对象,如果连接失败则返回None"""try:conn_str = f'DRIVER={{ODBC Driver 17 for SQL Server}};SERVER={server};DATABASE={database};UID={username};PWD={password}'return pyodbc.connect(conn_str, timeout=5)except pyodbc.Error as e:logger.error(f"连接到服务器 {server} 失败: {e}")return Nonedef execute_query(connection, query):"""执行SQL查询:param connection: 数据库连接对象:param query: SQL查询语句:return: 查询结果列表"""try:cursor = connection.cursor()cursor.execute(query)return cursor.fetchall()except pyodbc.Error as e:logger.error(f"执行查询时出错: {e}")return []def process_server(ip, username, password, query):"""处理单个服务器的查询:param ip: 服务器IP地址:param username: 数据库用户名:param password: 数据库密码:param query: SQL查询语句:return: 元组 (IP地址, 查询结果)"""start_time = time.time()logger.info(f"开始处理服务器 {ip}")try:conn = create_connection(ip, 'master', username, password)if conn:results = execute_query(conn, query)conn.close()end_time = time.time()processing_time = end_time - start_timelogger.info(f"服务器 {ip} 处理完成. 获取 {len(results)} 行数据. 耗时 {processing_time:.2f} 秒")return ip, resultsexcept Exception as e:logger.error(f"处理服务器 {ip} 时发生错误: {e}")logger.info(f"服务器 {ip} 处理失败")return ip, []def create_target_table(connection, table_name, columns):"""在目标数据库中创建表:param connection: 目标数据库连接对象:param table_name: 要创建的表名:param columns: 列定义列表"""try:cursor = connection.cursor()create_table_query = f"CREATE TABLE {table_name} (ServerIP VARCHAR(15), {', '.join(columns)})"cursor.execute(create_table_query)connection.commit()logger.info(f"成功创建表 {table_name}")except pyodbc.Error as e:logger.error(f"创建目标表时出错: {e}")raisedef insert_data(connection, table_name, data):"""将数据插入目标数据库:param connection: 目标数据库连接对象:param table_name: 目标表名:param data: 要插入的数据列表:return: 插入的行数"""try:cursor = connection.cursor()placeholders = ', '.join(['?' for _ in range(len(data[0]))])insert_query = f"INSERT INTO {table_name} VALUES ({placeholders})"cursor.fast_executemany = Truecursor.executemany(insert_query, data)connection.commit()return cursor.rowcountexcept pyodbc.Error as e:logger.error(f"插入数据时出错: {e}")connection.rollback()return 0def generate_table_name():"""生成随机表名:return: 生成的表名"""date_str = datetime.now().strftime("%Y%m%d")random_str = ''.join(random.choices(string.ascii_lowercase, k=5))return f"QueryResults_{date_str}_{random_str}"def main():"""主函数,协调整个数据查询和汇总过程"""try:# 读取配置config = read_config('config.ini')ip_list = read_ip_list(config['ip_list_file'])if not ip_list:logger.error("IP地址列表为空,程序终止")returnlogger.info(f"开始处理 {len(ip_list)} 个服务器")# 并发查询所有服务器results = []with ThreadPoolExecutor(max_workers=config['max_workers']) as executor:future_to_ip = {executor.submit(process_server, ip, config['source_db_username'], config['source_db_password'], config['query']): ip for ip in ip_list}for future in as_completed(future_to_ip):ip, result = future.result()if result:results.extend([(ip,) + tuple(row) for row in result])if not results:logger.info("没有查询到数据,程序终止")return# 连接目标数据库target_conn = create_connection(**config['target_db_info'])if not target_conn:logger.error("无法连接到目标数据库,程序终止")return# 创建目标表并插入数据table_name = generate_table_name()columns = [f"Column{i} VARCHAR(100)" for i in range(len(results[0]) - 1)]create_target_table(target_conn, table_name, columns)rows_inserted = insert_data(target_conn, table_name, results)target_conn.close()logger.info(f"数据汇总完成。插入 {rows_inserted} 行到表 {table_name}")print(f"查询结果已插入表: {table_name}")except Exception as e:logger.critical(f"程序执行过程中发生严重错误: {e}")print(f"程序执行过程中发生错误,请查看日志文件获取详细信息。")if __name__ == "__main__":main()

代码说明

  1. 配置文件读取:使用 configparser 模块读取配置文件,包括数据库连接信息、查询语句等。

  2. 多线程处理:使用 ThreadPoolExecutor 并发执行查询,提高效率。

  3. 异常处理:每个关键操作都包含了异常处理,确保程序的稳定性。

  4. 模块化设计:将不同功能分解为独立的函数,提高代码的可读性和可维护性。

  5. 日志记录:使用 logging 模块记录详细的操作日志,同时输出到文件和控制台。

  6. 动态表创建:在目标数据库中动态创建表,表名包含日期和随机字符串。

  7. 数据汇总:将所有服务器的查询结果汇总到一个列表中,包括服务器IP地址。

  8. 批量数据插入:使用 executemany 批量插入数据到目标表。

使用说明

  1. 创建 config.ini 配置文件,包含以下内容:
[Files]
ip_list_file = server_ip_list.txt[SourceDB]
username = your_source_username
password = your_source_password[TargetDB]
server = your_target_server
database = your_target_database
username = your_target_username
password = your_target_password[Settings]
max_workers = 50[Query]
sql = SELECT column1, column2 FROM your_table
  1. 准备一个包含要查询的服务器IP地址的文本文件(如 server_ip_list.txt)。

  2. 运行脚本,它将并发查询所有服务器,汇总结果(包括服务器IP),并插入到目标数据库的新表中。

  3. 脚本执行完成后,会输出生成的表名。

结论

这个Python脚本提供了一个高效、灵活的解决方案,可以批量测试数据库服务器连接、执行查询并汇总结果。它具有以下优点:

  • 并发处理,大幅提高效率
  • 详细的日志记录,便于监控和调试
  • 灵活的配置,易于适应不同环境
  • 异常处理完善,提高程序稳定性
  • 结果包含服务器IP,便于追踪数据来源

对于需要管理大量数据库服务器的运维人员来说,这个脚本可以显著提高工作效率。您可以根据实际需求进一步调整和优化这个脚本,例如添加更多的错误处理、优化查询性能,或者扩展功能以支持更复杂的操作。

通过使用这个脚本,您可以轻松地对多个数据库服务器进行批量操作,并将结果汇总到一个中心位置,大大简化了数据库管理和监控的工作流程。

相关文章:

Python 助力 DBA:高效批量管理数据库服务器的多线程解决方案-多库查询汇总工具实现

批量数据库服务器连接测试与数据汇总:Python实现方案 作为数据库服务器运维人员,我们经常需要面对大量服务器的连接测试和数据汇总工作。本文将介绍一个使用Python实现的高效解决方案,可以帮助我们快速完成这些任务。 需求概述 从配置文件…...

vue响应式数据-修改对象的属性值,视图不更新

如图: 一:问题是: 我把数据处理后能console.log()打印出来,但是页面的内容不能同步的更新渲染; 二:要求: 在数组循环列表里面,我点击单个的item按钮时,需要实时加载进度…...

【OpenCV计算机视觉】图像处理——平滑

本篇文章记录我学习【OpenCV】图像处理中关于“平滑”的知识点,希望我的分享对你有所帮助。 目录 一、什么是平滑处理 1、平滑的目的是什么? 2、常见的图像噪声 (1)椒盐噪声 ​编辑(2) 高斯噪声 &a…...

C#编程报错- “ComboBox”是“...ComboBox”和“...ComboBox”之间的不明确的引用

1、问题描述 在学习使用C#中的Winform平台编写一个串口助手程序时, 在编写一个更新ComboBox列表是遇到了问题,出错的代码是 2、报错信息 CS1503 参数 2: 无法从“System.Windows.Forms.ComboBox”转换为“System.Windows.Forms.ComboBox” CS1503 …...

JAVA:访问者模式(Visitor Pattern)的技术指南

1、简述 访问者模式(Visitor Pattern)是一种行为型设计模式,允许你将操作分离到不同的对象中,而无需修改对象本身的结构。这种模式特别适合复杂对象结构中对其元素进行操作的场景。 本文将介绍访问者模式的核心概念、优缺点,并通过详细代码示例展示如何在实际应用中实现…...

YashanDB共享集群产品能力观测:细节足见功底

本文基于前泽塔数科研发总监-王若楠2024年11月在“2024年国产数据库创新生态大会”-“根”技术专场的演讲整理形成,主要对崖山共享集群YAC的架构、功能、高可用性、性能四大方面进行全面测试,并分享了测试环境和测试结论。 年初,基于某些商业…...

【Linux】—简单实现一个shell(myshell)

大家好呀,我是残念,希望在你看完之后,能对你有所帮助,有什么不足请指正!共同学习交流哦! 本文由:残念ing原创CSDN首发,如需要转载请通知 个人主页:残念ing-CSDN博客&…...

@FeignClient用于Nacos微服务间的接口调用

依赖&#xff1a;<!-- spring-boot启动依赖 --> <!-- 提供者 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- openFeign --> <…...

认识javascript中的模块化

什么是模块化&#xff1f; 将程序⽂件依据⼀定规则拆分成多个文件&#xff0c;拆分出来每个⽂件就是⼀个模块&#xff0c;模块中的数据都是私有的&#xff0c;模块之间互相隔离。如果不进行隔离&#xff0c;可能会造成模块间的变量定义有冲突&#xff0c;导致程序崩溃 为啥要使…...

容器设计模式:Sidecar

文章目录 容器设计模式&#xff1a;Sidecar 模式1. 什么是 Sidecar 模式&#xff1f;2. Sidecar 模式的原理2.1 工作机制2.2 常见用途 3. Sidecar 模式示例示例&#xff1a;日志收集 4. Sidecar 模式的架构图图例&#xff1a; 5. Sidecar 模式的优点6. Sidecar 模式的局限性7. …...

ensp 静态路由配置

A公司有广州总部、重庆分部和深圳分部3个办公地点&#xff0c;各分部与总部之间使用路由器互联。广州、重庆、深圳的路由器分别为R1、R2、R3&#xff0c;为路由器配置静态路由&#xff0c;使所有计算机能够互相访问&#xff0c;实训拓扑图如图所示 绘制拓扑图 给pc机配置ip地址…...

MATLAB图卷积神经网络GCN处理分子数据集节点分类研究

全文链接&#xff1a;https://tecdat.cn/?p38570 本文主要探讨了如何利用图卷积网络&#xff08;GCN&#xff09;对图中的节点进行分类。介绍了相关的数据处理、模型构建、训练及测试等环节&#xff0c;通过对分子数据集的操作实践&#xff0c;展示了完整的节点分类流程&#…...

Android-Glide详解

目录 一&#xff0c;介绍 二&#xff0c;使用 三&#xff0c;源码分析思路 四&#xff0c;with源码分析 五&#xff0c;模拟Glide生命周期管理 一&#xff0c;介绍 Glide目前是安卓最主流的加载图片的框架&#xff0c;也是源码最为复杂的框架之一。 要想完完全全吃透Glide的源…...

2.Nuxt学习 组件使用和路由跳转相关

组件定义和使用 普通组件的使用 在Nuxt的项目中&#xff0c;可以直接在components文件夹下建立组件 在页面中直接使用 无需引入 多层级组件的使用 我们有时候会需要多层级组件来简化代码结构 比如我们需要给Banner组件添加一个子组件 我们直接建立其名称的文件夹 写入子组…...

代码开发相关操作

使用Vue项目管理器创建项目&#xff1a;&#xff08;vue脚手架安装一次就可以全局使用&#xff09; windowR打开命令窗口&#xff0c;输入vue ui&#xff0c;进入GUI页面&#xff0c;点击创建-> 设置项目名称&#xff0c;在初始化git下面输入&#xff1a;init project&…...

动态导出word文件支持转pdf

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、功能说明二、使用步骤1.controller2.工具类 DocumentUtil 导出样式 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 例如&#xff…...

登陆harbor发现证书是错误的, 那么如何更新harbor的证书呢

Error response from daemon: Get "https://172.16.21.35/v2/": tls: failed to verify certificate: x509: certificate is valid for 127.0.0.1, ::1, 172.16.21.30, not 172.16.21.35 版本 v2.10.1-b7b88476 不需要从头看, 直接看最下面的成功的证书创建 这里面首…...

【Leetcode Top 100】199. 二叉树的右视图

问题背景 给定一个二叉树的 根节点 r o o t root root&#xff0c;想象自己站在它的右侧&#xff0c;按照从顶部到底部的顺序&#xff0c;返回从右侧所能看到的节点值。 数据约束 二叉树的节点个数的范围是 [ 0 , 100 ] [0,100] [0,100] − 100 ≤ N o d e . v a l ≤ 100…...

React自学:如何使用localStorage,以及如何实现删除笔记操作

1. 初始化notes 以下这段代码完成了这些操作&#xff1a; 调用 localStorage.getItem("notes") 从浏览器的本地存储中获取名为 “notes” 的数据。使用 JSON.parse 将获取到的字符串解析成数组。如果本地存储中没有 “notes” 数据&#xff08;返回值为 null&#…...

go语言使用websocket发送一条消息A,持续接收返回的消息

在Go语言中实现一个WebSocket客户端&#xff0c;可以使用gorilla/websocket这个非常流行的库来处理WebSocket连接。下面是一个简单的示例&#xff0c;展示了如何创建一个WebSocket客户端&#xff0c;向服务器发送消息"A"&#xff0c;并持续接收来自服务器的响应。 首…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式

今天是关于AI如何在教学中增强学生的学习体验&#xff0c;我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育&#xff0c;这并非炒作&#xff0c;而是已经发生的巨大变革。教育机构和教育者不能忽视它&#xff0c;试图简单地禁止学生使…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...

保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!

目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...

raid存储技术

1. 存储技术概念 数据存储架构是对数据存储方式、存储设备及相关组件的组织和规划&#xff0c;涵盖存储系统的布局、数据存储策略等&#xff0c;它明确数据如何存储、管理与访问&#xff0c;为数据的安全、高效使用提供支撑。 由计算机中一组存储设备、控制部件和管理信息调度的…...

职坐标物联网全栈开发全流程解析

物联网全栈开发涵盖从物理设备到上层应用的完整技术链路&#xff0c;其核心流程可归纳为四大模块&#xff1a;感知层数据采集、网络层协议交互、平台层资源管理及应用层功能实现。每个模块的技术选型与实现方式直接影响系统性能与扩展性&#xff0c;例如传感器选型需平衡精度与…...