Python 每秒向MySQL表插入数据(每秒一次)
我是Python、Raspberry Pi和MySQL的新手,希望您能帮助我。我正在尝试用Python编写一个脚本,它可以每秒将数据插入MySQL表。我可以插入数据,但不是我想要的周期性数据,我已经尝试了很多,但我找不到解决问题的方法。下面是我的Python代码和插入MySQL表的数据: Python代码: 表格结果: 如您所见,有时纸条会周期性地插入数据,有时数据之间有8秒的间隔。所以,我的问题是:每次数据之间的间隔是否可能是1秒?我做错了什么?Python 每秒向MySQL表插入数据(每秒一次),python,mysql,raspberry-pi,raspberry-pi2,Python,Mysql,Raspberry Pi,Raspberry Pi2,我是Python、Raspberry Pi和MySQL的新手,希望您能帮助我。我正在尝试用Python编写一个脚本,它可以每秒将数据插入MySQL表。我可以插入数据,但不是我想要的周期性数据,我已经尝试了很多,但我找不到解决问题的方法。下面是我的Python代码和插入MySQL表的数据: Python代码: 表格结果: 如您所见,有时纸条会周期性地插入数据,有时数据之间有8秒的间隔。所以,我的问题是:每次数据之间的间隔是否可能是1秒?我做错了什么? 抱歉英语不好,提前谢谢 不要为此使用事务,当尝
抱歉英语不好,提前谢谢 不要为此使用事务,当尝试插入新行时,可能某些表被锁定。您在每次迭代中都要建立到数据库服务器的新连接。这可能需要任意的时间。将
.connect()
等移动到循环之外可能会使计时更加一致:
db = MySQLdb.connect("localhost", "mauro", "12345", "temps")
curs = db.cursor()
while True:
try:
curs.execute ("""INSERT INTO thetemps
values(0, CURRENT_DATE(), NOW(), 28)""")
db.commit()
print "Data committed"
except:
print "Error"
db.rollback()
time.sleep(1)
db.close()
尝试在之前创建与db的连接,同时保持连接的打开状态。我看到的问题是连接+插入需要时间,这将累积起来,您的进程最终将落后 我要做的是将数据收集(确保每秒读取一次温度)与数据加载分开(如果需要,数据加载可能需要一秒钟以上的时间,但不会落后) 所以,如果我是你,我会有两个独立的脚本并行运行,并通过一些简单、快速和可靠的机制进行通信。在中列出一个列表可能会很有用。你也可以用类似的东西 大概是这样的:
# gather.py
while True:
temp = get_temp()
redis.lpush('temps', pickle.dumps([temp, datetime.now]))
time.sleep(1)
和
您可以在上面添加一些改进,比如重用db连接、确保在出现db错误时不会丢失TEMP、为数据点使用namedtuple而不是数组等
每次数据之间的间隔是否可能为1秒
理论上是的,但实际上有太多其他因素超出了你的控制范围,更可能成为阻碍。其中包括但不限于:
time.sleep(1)
也不能保证总是睡眠1秒钟,即使如此,系统也可能一直在做其他事情(例如,更多的I/O),每次都需要不同的时间来执行相同的操作
此外,不要每次在循环中创建新连接,而应该保持连接打开并节省开销
我做错了什么
我不认为你在这里做错了什么。代码看起来没问题,除了每次创建新连接的额外开销之外,您不应该这样做。除此之外,这里的问题归结为您无法控制的因素
也就是说,你可以做一些事情来提高你的机会
提高性能的一些附加建议 存储引擎 除了避免每次迭代时打开/关闭数据库连接的开销外,还应该检查用于表的存储引擎。例如,根据您的MySQL版本,默认值可能仍然是
MyISAM
,这需要表锁定才能写入
相反,InnoDB
在写入表时只需要行锁定,如果其他人正在使用表,这应该会有所改善。如果发现没有使用InnoDB
,请发出alter table…
查询以更改存储引擎
自动提交而不是事务
事务意味着将一组2个或多个查询作为单个单元进行分组,但您提交的是单个查询。相反,您应该将MySQL配置为启用自动提交,以便在提交和执行查询后,它不必等待显式的commit
请求,从而节省服务器和客户端之间的一些通信开销
通过增加优先级来影响操作系统调度程序
您可以为您的程序设置更高的优先级,以使调度程序在此处更有帮助。它还可能有助于对数据库服务/进程执行相同的操作
如有必要,其他用户级任务的优先级也可以降低一点。将
.connect
和.close
放在while循环之外,这样就不需要每次都重新初始化。这并不能保证任何事情,但它可能更加一致。您可以做的另一件事是不使用时间。sleep
您可以读取表中的最后一个时间值,然后在这之后的第二秒执行您的命令,以确定发生了什么,您需要对python进程和mysqld进行扫描(使用-tt获取时间戳)。如果您只是想猜测,除了已经说过的内容,如果表是InnoDB,请更改表thetemps ENGINE=MYISAM。Raspberry PI可能没有足够的umph来有效地处理InnoDB表。事务提交可能需要一段时间。请不要忘记返回并接受您认为对您最有用的答案。这对你、那些试图解决你的问题的人以及整个社区的其他人都有好处。谢谢@SashaPachev!!这使我的脚本工作,因为我想+1对于这个想法,尽管我认为实现^^与OP有相同的问题:connect()
,等等。可能需要任意的时间,时间戳(NOW()
)的差异可能超过1s。@eugeney是的,我重新阅读了代码,出现了一系列错误。试图修复它们,尽管它更像是一个通用id
db = MySQLdb.connect("localhost", "mauro", "12345", "temps")
curs = db.cursor()
while True:
try:
curs.execute ("""INSERT INTO thetemps
values(0, CURRENT_DATE(), NOW(), 28)""")
db.commit()
print "Data committed"
except:
print "Error"
db.rollback()
time.sleep(1)
db.close()
# gather.py
while True:
temp = get_temp()
redis.lpush('temps', pickle.dumps([temp, datetime.now]))
time.sleep(1)
# load.py
while True:
# Block until new temps are available in redis
data, key = redis.brpop('temps')
# Get all temps queued
datapoints = [data] + redis.rpop('temps'):
db = MySQLdb.connect("localhost", "mauro", "12345", "temps")
curs=db.cursor()
try:
for p in datapoints:
point = pickle.loads(p)
curs.execute ("INSERT INTO thetemps (temp, timestamp) values({}, {})".format(point[0], point[1])
db.commit()
print "Data committed"
except:
print "Error"
db.rollback()