每秒将数据插入MySQL表(每秒一次)

时间:2015-11-06 21:52:23

标签: python mysql raspberry-pi raspberry-pi2

我是Python,Raspberry Pi和MySQL的新手,我希望你能帮助我。我试图在Python中编写一个可以每秒将数据插入MySQL表的脚本。我可以插入数据,但不像我想要的那样是周期性的,我已经尝试了很多,但我无法找到问题的解决方案。这是我的Python代码和插入MySQL表的数据:

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)

表结果:

+-----+------------+----------+------+
| 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秒吗?我究竟做错了什么? 对不起英语不好,提前谢谢!

5 个答案:

答案 0 :(得分:2)

您正在每次迭代时建立与数据库服务器的新连接。这可能需要任意时间。在循环之外移动.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()

答案 1 :(得分:1)

当尝试插入新行时,不要使用事务,也许某些表被锁定。

答案 2 :(得分:1)

  

每次数据之间的间隔可能是1秒吗?

理论上,是的,但在实践中,有太多其他因素超出您的控制范围,更有可能妨碍您。其中一些包括但不限于:

  1. OS内核的任务调度程序
  2. 相对于他人的任务优先级
  3. 整体系统负载
  4. 表中已有的数据量(检查二叉树的时间复杂度)
  5. 这意味着即使您的系统在大多数时间处于空闲状态,time.sleep(1)也不能保证始终在完全 1秒内休眠,即使这样做,系统也可能一直在做其他事情(例如更多的I / O),并且每次都需要不同的时间来执行相同的操作。

    此外,不是每次在循环内创建 new 连接,都应该保持连接打开并节省开销。

      

    我做错了什么?

    我不认为你在这里做任何特别错误的事情。代码看起来没问题,除了,因为每次创建一个新连接的额外开销 - 你不应该。除此之外,这里的问题归结为你无法控制的因素。

    话虽如此,你可以采取一些措施来提高你的机会。

    提高性能的一些其他建议

    存储引擎

    除了避免在每次迭代时打开/关闭数据库连接的开销之外,还应检查用于表的存储引擎。例如,根据您的MySQL版本,默认值可能仍为MyISAM,这需要 table 锁定才能写入。

    相比之下,InnoDB在写入表时只需要锁定,如果其他人正在使用该表,这应该会改进。如果您发现未使用InnoDB,请发出alter table ...查询以更改存储引擎。

    自动提交而不是交易

    交易意味着将2个或更多查询的分组为一个单元,但您提交的是个人查询。相反,您应该将MySQL配置为启用自动提交,以便在提交和执行查询后不必等待显式commit请求,从而节省服务器和客户端之间的一些通信开销。 / p>

    通过提高优先级来影响OS计划程序

    您可以为程序设置更高的优先级,以便调度程序在此处更有用。它也可能有助于为数据库服务/进程做同样的事情。

    其他用户级别的任务也可以在必要时降低其优先级。

答案 3 :(得分:0)

尝试在while条件之前创建与db的连接以保持打开连接。

答案 4 :(得分:0)

我看到的问题是连接+插入需要时间,这会加起来,你的过程最终会落后。

我要做的是从数据加载中分离数据收集(确保您每秒读取一次温度)(如果需要,数据加载可能需要超过一秒钟,但您不会落后)。 / p>

所以,如果我是你,我会有两个独立的脚本并行运行,并通过一些简单,快速和可靠的机制进行通信。 Redis中的列表可能效果很好。您还可以使用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()

您可以在上面添加一些改进,例如重用数据库连接,确保如果出现数据库错误,使用namedtuple而不是数组用于数据点等,就不会丢失临时值。