每秒向MySQLtable插入数据(每秒一次)
Insert data to MySQL table every second (one time per second)
我是 Python、Raspberry Pi 和 MySQL 的新人,希望您能帮助我。我正在尝试在 Python 中编写一个脚本,它可以每秒将数据插入 MySQL table。我可以插入数据但不像我想要的那样定期插入,我已经尝试了很多但我找不到解决我的问题的方法。这是我的 Python 代码和插入到 MySQL table 中的数据:
Python代码:
#!/usr/bin/env python
import MySQLdb
import time
while True:
db = MySQLdb.connect("localhost", "mauro", "12345", "temps")
curs=db.cursor()
try:
curs.execute ("""INSERT INTO thetemps
values(0, CURRENT_DATE(), NOW(), 28)""")
db.commit()
print "Data committed"
except:
print "Error"
db.rollback()
db.close()
time.sleep(1)
Table 结果:
+-----+------------+----------+------+
| id | date | time | temp |
+-----+------------+----------+------+
| 107 | 2015-11-06 | 19:16:41 | 28 |
| 108 | 2015-11-06 | 19:16:42 | 28 |
| 109 | 2015-11-06 | 19:16:45 | 28 |
| 110 | 2015-11-06 | 19:16:46 | 28 |
| 111 | 2015-11-06 | 19:16:47 | 28 |
| 112 | 2015-11-06 | 19:16:48 | 28 |
| 113 | 2015-11-06 | 19:16:56 | 28 |
| 114 | 2015-11-06 | 19:17:00 | 28 |
| 115 | 2015-11-06 | 19:17:03 | 28 |
| 116 | 2015-11-06 | 19:17:05 | 28 |
| 117 | 2015-11-06 | 19:17:06 | 28 |
| 118 | 2015-11-06 | 19:17:07 | 28 |
| 119 | 2015-11-06 | 19:17:08 | 28 |
| 120 | 2015-11-06 | 19:17:09 | 28 |
| 121 | 2015-11-06 | 19:17:10 | 28 |
| 122 | 2015-11-06 | 19:17:11 | 28 |
+-----+------------+----------+------+
如您所见,有时脚本会定期插入数据,有时数据之间有 8 秒的间隔。所以,我的问题是:每次数据之间的间隔是否可以为1秒?我究竟做错了什么?
抱歉英语不好,提前致谢!
不要为此使用事务,可能一些 table 在尝试插入新行时被锁定。
您将在每次迭代中建立与数据库服务器的新连接。这可能需要任意时间。将 .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()
尝试在 while 条件之前创建与数据库的连接以保持连接打开。
我看到的问题是连接+插入需要时间,这会加起来,你的过程最终会落后。
我要做的是将数据收集(确保您每秒读取一次温度)与数据加载分开(如果需要,数据加载可能需要一秒以上的时间,但您不会落后)。
所以,如果我是你,我会有两个并行的独立脚本 运行,并通过一些简单、快速和可靠的机制进行通信。 Redis would probably work great. You could also use something like ZMQ.
中的列表
像这样:
# 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()
您可以在上面添加一些改进,例如重用数据库连接,确保在出现数据库错误时不会丢失临时数据,使用命名元组而不是数据点数组等。
is possible to the interval between the data be 1 second every time?
理论上是的,但在实践中,有太多您无法控制的其他因素更有可能成为障碍。其中一些包括但不限于:
- OS 内核的任务调度器
- 相对于其他任务的优先级
- 整体系统负载
- table中已有的数据量(检查二叉树的时间复杂度)
这意味着即使您的系统大部分时间都处于空闲状态,time.sleep(1)
也不能保证总是休眠 正好 1 秒,即使它确实如此,系统可能一直在做其他事情(例如更多I/O)并且每次执行相同的操作需要不同的时间。
此外,与其在循环内每次都创建一个 new 连接,不如保持连接打开并节省开销。
What am i doing wrong?
我不认为你在这里做错了什么。代码看起来不错,除了每次创建新连接的额外开销——你不应该。除此之外,这里的问题归结为您无法控制的因素。
话虽这么说,但您可以采取一些措施来提高成功率。
一些提高性能的额外建议
存储引擎
除了避免每次迭代 opening/closing 数据库连接的开销外,您还应该检查用于 table 的存储引擎。例如,根据您的 MySQL 版本,默认值可能仍然是 MyISAM
,这需要 table 锁定才能写入。
相比之下,InnoDB
在写入 table 时只需要 行 锁定,如果其他东西正在使用 [=82],这应该会有所改善=].如果您发现自己没有使用 InnoDB
,请发出 alter table ...
查询以更改存储引擎。
自动提交而不是交易
事务旨在将 2 个或更多查询的 集 分组为一个单元,但您提交的是 单个 查询。相反,您应该配置 MySQL 以启用自动提交,这样它就不必在提交和执行查询后等待明确的 commit
请求,从而节省服务器和服务器之间的一些通信开销你的客户。
通过提高优先级来影响 OS 调度程序
您可以为您的程序设置更高的优先级,以便调度程序在这里更有帮助。它也可能有助于为数据库做同样的事情 service/process.
如有必要,其他用户级任务的优先级也可以降低一点。
我是 Python、Raspberry Pi 和 MySQL 的新人,希望您能帮助我。我正在尝试在 Python 中编写一个脚本,它可以每秒将数据插入 MySQL table。我可以插入数据但不像我想要的那样定期插入,我已经尝试了很多但我找不到解决我的问题的方法。这是我的 Python 代码和插入到 MySQL table 中的数据:
Python代码:
#!/usr/bin/env python
import MySQLdb
import time
while True:
db = MySQLdb.connect("localhost", "mauro", "12345", "temps")
curs=db.cursor()
try:
curs.execute ("""INSERT INTO thetemps
values(0, CURRENT_DATE(), NOW(), 28)""")
db.commit()
print "Data committed"
except:
print "Error"
db.rollback()
db.close()
time.sleep(1)
Table 结果:
+-----+------------+----------+------+
| id | date | time | temp |
+-----+------------+----------+------+
| 107 | 2015-11-06 | 19:16:41 | 28 |
| 108 | 2015-11-06 | 19:16:42 | 28 |
| 109 | 2015-11-06 | 19:16:45 | 28 |
| 110 | 2015-11-06 | 19:16:46 | 28 |
| 111 | 2015-11-06 | 19:16:47 | 28 |
| 112 | 2015-11-06 | 19:16:48 | 28 |
| 113 | 2015-11-06 | 19:16:56 | 28 |
| 114 | 2015-11-06 | 19:17:00 | 28 |
| 115 | 2015-11-06 | 19:17:03 | 28 |
| 116 | 2015-11-06 | 19:17:05 | 28 |
| 117 | 2015-11-06 | 19:17:06 | 28 |
| 118 | 2015-11-06 | 19:17:07 | 28 |
| 119 | 2015-11-06 | 19:17:08 | 28 |
| 120 | 2015-11-06 | 19:17:09 | 28 |
| 121 | 2015-11-06 | 19:17:10 | 28 |
| 122 | 2015-11-06 | 19:17:11 | 28 |
+-----+------------+----------+------+
如您所见,有时脚本会定期插入数据,有时数据之间有 8 秒的间隔。所以,我的问题是:每次数据之间的间隔是否可以为1秒?我究竟做错了什么? 抱歉英语不好,提前致谢!
不要为此使用事务,可能一些 table 在尝试插入新行时被锁定。
您将在每次迭代中建立与数据库服务器的新连接。这可能需要任意时间。将 .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()
尝试在 while 条件之前创建与数据库的连接以保持连接打开。
我看到的问题是连接+插入需要时间,这会加起来,你的过程最终会落后。
我要做的是将数据收集(确保您每秒读取一次温度)与数据加载分开(如果需要,数据加载可能需要一秒以上的时间,但您不会落后)。
所以,如果我是你,我会有两个并行的独立脚本 运行,并通过一些简单、快速和可靠的机制进行通信。 Redis would probably work great. You could also use something like ZMQ.
中的列表像这样:
# 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()
您可以在上面添加一些改进,例如重用数据库连接,确保在出现数据库错误时不会丢失临时数据,使用命名元组而不是数据点数组等。
is possible to the interval between the data be 1 second every time?
理论上是的,但在实践中,有太多您无法控制的其他因素更有可能成为障碍。其中一些包括但不限于:
- OS 内核的任务调度器
- 相对于其他任务的优先级
- 整体系统负载
- table中已有的数据量(检查二叉树的时间复杂度)
这意味着即使您的系统大部分时间都处于空闲状态,time.sleep(1)
也不能保证总是休眠 正好 1 秒,即使它确实如此,系统可能一直在做其他事情(例如更多I/O)并且每次执行相同的操作需要不同的时间。
此外,与其在循环内每次都创建一个 new 连接,不如保持连接打开并节省开销。
What am i doing wrong?
我不认为你在这里做错了什么。代码看起来不错,除了每次创建新连接的额外开销——你不应该。除此之外,这里的问题归结为您无法控制的因素。
话虽这么说,但您可以采取一些措施来提高成功率。
一些提高性能的额外建议
存储引擎
除了避免每次迭代 opening/closing 数据库连接的开销外,您还应该检查用于 table 的存储引擎。例如,根据您的 MySQL 版本,默认值可能仍然是 MyISAM
,这需要 table 锁定才能写入。
相比之下,InnoDB
在写入 table 时只需要 行 锁定,如果其他东西正在使用 [=82],这应该会有所改善=].如果您发现自己没有使用 InnoDB
,请发出 alter table ...
查询以更改存储引擎。
自动提交而不是交易
事务旨在将 2 个或更多查询的 集 分组为一个单元,但您提交的是 单个 查询。相反,您应该配置 MySQL 以启用自动提交,这样它就不必在提交和执行查询后等待明确的 commit
请求,从而节省服务器和服务器之间的一些通信开销你的客户。
通过提高优先级来影响 OS 调度程序
您可以为您的程序设置更高的优先级,以便调度程序在这里更有帮助。它也可能有助于为数据库做同样的事情 service/process.
如有必要,其他用户级任务的优先级也可以降低一点。