You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多实例Python应用仅首个能写入MariaDB表问题排查请求

问题分析与原因排查

问题描述

我在多台Raspberry Pi上运行基于Python 3.12.3的应用,MariaDB 10.5.21部署在单独的专用Pi上。应用会定时获取UPS数据,并通过存储过程将数据写入公共表。单实例运行时一切正常,但多实例运行时,只有第一个启动的实例能向表中写入数据;若停止第一个实例并重启第二个,第二个实例可正常写入,第一个则无法写入。相关代码如下:

数据写入代码

# Save the poll value to the database
conn = DatabaseConnection()
cur = conn.cursor()
cur.execute("CALL ups_poll_ins(?, ?, ?, ?, ?, ?, ?)",(ups.PiId, ups.SerialNo, ups.Status == 'ONLINE', ups.Load, ups.BatteryCharge, ups.TimeLeft, ups.TimeOnBattery))
conn.commit()
cur.close()
conn.close()

数据库连接函数

def DatabaseConnection():
    config = configparser.ConfigParser()
    config.sections()
    config.read('/opt/database.ini')

    return mariadb.connect(
        host=config['DATABASE']['Host'],
        user=config['DATABASE']['User'],
        password = config['DATABASE']['Password'],
        database="home_monitoring",
        autocommit=True)

可能的原因

核心问题大概率出在ups_poll_ins存储过程的逻辑上,而非Python代码:

  • 存储过程持有排他锁未释放:如果存储过程里执行了LOCK TABLES ups_poll WRITE这类表级锁操作,却没有在结束时调用UNLOCK TABLES,第一个实例调用存储过程后会一直持有锁,后续实例的写入请求会被阻塞,直到第一个实例的数据库连接关闭(停止实例时才会释放)。
  • 存储过程内部事务未正确提交:虽然你的连接设置了autocommit=True,但如果存储过程内部手动开启了事务(比如START TRANSACTION),却没有在结束时显式执行COMMIT或ROLLBACK,第一个实例的事务会一直占用锁资源,导致后续实例无法写入。

排查与解决建议

  1. 检查ups_poll_ins存储过程的代码,确认是否存在锁表语句或未正确处理的事务:
    • 若有LOCK TABLES,必须在存储过程末尾添加UNLOCK TABLES;
    • 若有手动事务,确保每个分支都有对应的COMMIT或ROLLBACK。
  2. 当第二个实例无法写入时,登录MariaDB执行SHOW PROCESSLIST;,查看第二个实例的线程状态:
    • 如果状态是Waiting for table metadata lock或Waiting for table level lock,就能确认是锁资源被占用导致的问题。
  3. 你当前的Python代码已经在调用存储过程后立即关闭连接,这一步没问题,核心还是要修复存储过程的锁/事务逻辑。

内容的提问来源于stack exchange,提问作者Byron S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 10:12:41