多实例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,第一个实例的事务会一直占用锁资源,导致后续实例无法写入。
排查与解决建议
- 检查
ups_poll_ins存储过程的代码,确认是否存在锁表语句或未正确处理的事务:- 若有
LOCK TABLES,必须在存储过程末尾添加UNLOCK TABLES; - 若有手动事务,确保每个分支都有对应的
COMMIT或ROLLBACK。
- 若有
- 当第二个实例无法写入时,登录MariaDB执行
SHOW PROCESSLIST;,查看第二个实例的线程状态:- 如果状态是
Waiting for table metadata lock或Waiting for table level lock,就能确认是锁资源被占用导致的问题。
- 如果状态是
- 你当前的Python代码已经在调用存储过程后立即关闭连接,这一步没问题,核心还是要修复存储过程的锁/事务逻辑。
内容的提问来源于stack exchange,提问作者Byron S
相关产品推荐
相关产品推荐

