python:多线程写入数据到数据库

代码功能:

以多线程的方式一边读取容器占用cpu和内存资源,一边将获得的数据写入数据库

完整代码如下:

""" 
******************************************************************************************
*                                   多线程写入数据库-最终版                                      
*-----------------------------------------------------------------------------------------
* 注意:pymysql多线程读写数据库报错:Packet sequence number wrong 
*   解决方法:  每个execute前加上互斥锁
*               lock.acquire()
*               cursor.execute(command,data)
*               lock.release()
*
******************************************************************************************
"""
import pymysql.cursors
import threading
import time
import docker


# -------------------------- 初始化 -------------------------------
print('程序初始化...')
print('建立数据库连接...')
# 创建数据库连接
cnx = pymysql.connect(host='localhost', port=3306, user='root', password='123456', db='qt', charset='utf8mb4',connect_timeout=20)
cursor = cnx.cursor()
# 定义容器名列表
container_names = ['a','b','c','d','e','f','g']  

# 创建锁
lock = threading.Lock()
# -------------------------- docker stats读取 -------------------------------
def get_container_stats(container_name):
    client = docker.from_env() # 假设你已经初始化了 Docker 客户端
    container = client.containers.get(container_name)

    stats = container.stats(stream=False)
    cpu_usage = 100 * stats['cpu_stats']['cpu_usage']['total_usage'] / stats['cpu_stats']['system_cpu_usage']
    memory_used = 100 * stats['memory_stats']['usage'] / stats['memory_stats']['limit']

    return cpu_usage, memory_used

# -------------------------- 数据库写入 -------------------------------
def mysql_data_update(container_name, cursor, cnx):
    cpu_usage, memory_used = get_container_stats(container_name)
    # 将容器状态写入数据库
    # 执行更新数据的 SQL 语句
    lock.acquire()
    cursor.execute("UPDATE container_stats SET cpu_usage = %s, memory_used = %s WHERE container_name = %s", [cpu_usage, memory_used, container_name])
    # 提交事务
    cnx.commit()
    lock.release()
    print('容器:{} 成功写入数据库'.format(container_name))

# -------------------------- 多线程 ------------------------------------
def refresh_stats(container_names, interval=1):
    while True:
        start_time = time.time()
        
        # 创建线程列表
        threads = []
        
        # 多线程1:读取容器cpu,mem
        for container_name in container_names:
            # 创建并启动线程
            thread = threading.Thread(target=mysql_data_update, args=(container_name, cursor, cnx))
            thread.start()
            threads.append(thread)

        # 等待所有线程结束
        for thread in threads:
            thread.join()
        
        end_time = time.time()
        total_time = end_time - start_time
        
        print("总时间: {:.2f} 秒".format(total_time))
        print("---------------------------------------------------------------------------------------------\n")
        time.sleep(interval)

# 调用函数进行实时刷新
refresh_stats(container_names)

代码解释

  1. 引入所需的模块:pymysql.cursors用于数据库连接和操作,threading用于多线程操作,time用于时间相关的操作,docker用于与 Docker 进行交互。

  2. get_container_stats函数:该函数通过 Docker 客户端获取指定容器的 CPU 和内存使用情况。

  3. mysql_data_update函数:该函数用于将容器的 CPU 和内存使用情况写入数据库。它首先调用 get_container_stats函数获取容器的使用情况,然后执行 SQL 语句将数据更新到数据库中。

  4. refresh_stats函数:该函数是多线程的核心部分。它使用一个无限循环来定期刷新容器的状态。在每次循环中,它创建多个线程来处理不同的容器,并调用mysql_data_update函数将容器的使用情况写入数据库。每个线程负责一个容器的处理。线程创建后,它们被添加到线程列表中,并在循环结束时等待所有线程执行完毕。之后,程序会休眠一段时间(由interval参数指定),然后再次开始新的循环。

注意:

for container_name in container_names 是一个循环语句,它用于遍历一个名为 container_names 的列表(或可迭代对象)中的每个元素,并将每个元素赋值给变量 container_name

在这段代码中,container_names 是一个包含容器名字的列表。通过使用循环语句,程序可以逐个遍历 container_names 列表中的容器名字,并将每个容器名字赋值给变量 container_name。在循环的每次迭代中,程序可以对每个容器执行相应的操作或处理。

换句话说,这个循环用于迭代处理 container_names 列表中的容器名字,以便在后续代码中使用这些容器名字执行相应的操作。

同时,代码中使用了互斥锁(lock)来确保在执行cursor.execute语句时的线程安全性,以避免出现报错:"Packet sequence number wrong"。在执行cursor.execute之前获取锁(lock.acquire()),在执行完毕后释放锁(lock.release())。 

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Python中,多线程写入数据库可以通过使用线程池来实现。下面是一个示例代码,演示了如何使用多线程同时写入数据库: ```python import threading import pymysql def write_to_database(data): # 连接数据库 conn = pymysql.connect(host='localhost', user='username', password='password', database='dbname') cursor = conn.cursor() # 执行插入操作 try: # 根据需要执行SQL语句,这里以插入操作为例 sql = "INSERT INTO table_name(column1, column2) VALUES (%s, %s)" cursor.execute(sql, (data['value1'], data['value2'])) conn.commit() print(f"Data {data} inserted successfully.") except Exception as e: conn.rollback() print(f"Error occurred while inserting data {data}: {e}") finally: # 关闭数据库连接 cursor.close() conn.close() # 创建数据列表 data_list = [ {'value1': 'data1', 'value2': 'data2'}, {'value1': 'data3', 'value2': 'data4'}, {'value1': 'data5', 'value2': 'data6'}, # 可以继续添加更多的数据 ] # 设置线程池大小 thread_pool_size = 5 # 创建线程池 thread_pool = [] # 创建线程并启动 for data in data_list: thread = threading.Thread(target=write_to_database, args=(data,)) thread_pool.append(thread) thread.start() # 等待所有线程执行完毕 for thread in thread_pool: thread.join() print("All threads have finished writing to the database.") ``` 在上述代码中,我们首先定义了一个`write_to_database`函数,用于执行数据库写入操作。然后,我们创建了一个数据列表,其中包含要写入数据库数据。接下来,我们设置了线程池的大小,并创建了一个空的线程池列表。然后,我们使用循环创建线程,并将每个线程添加到线程池中。最后,我们使用`join`方法等待所有线程执行完毕。 请注意,在多线程写入数据库时,需要确保数据库连接和游标对象的正确使用和关闭。此外,如果多个线程同时写入相同的数据库表,可能会出现竞态条件或锁问题,需要根据具体情况考虑使用适当的并发控制机制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值