在固定间隔开始获取空结果之后,为什么对LIVE表运行相同的查询?

时间:2019-02-08 16:32:10

标签: python sql-server python-3.x sql-server-2012 pyodbc

我有一个Python程序,每隔10分钟查询一次存储在SQL Server中的LIVE更新表。第一次执行时,它会返回正确的结果。最终,即使表实际上包含新数据,查询也开始返回空结果。我观察到几个小时后查询确实提取了数据。我想知道为什么查询没有在表中实际可用时获取结果?

使用的工具

我的python程序是使用pyodbc库用Python3编写的,以连接到存储视图的REMOTE SQL Server 12。该视图从不断更新的表中获取数据。我的程序分为多个文件。该程序的一个模块产生一个线程进程,该进程生成一个包含两个变量的SQL查询字符串。其中一个变量是在启动线程之前计算的,而第二个变量是一个值,该值会不断更改SQL查询。

想法

这个想法是继续从表中提取事件号(不断添加新的事件号)。因此,线程每10分钟保持运行一次查询,以检查是否有新的事件号。 SQL查询包含一个WHERE条件,该条件表示拉出事件编号> last_pulled_event_number。该“ last_pulled_event_number”是根据查询返回的结果计算的。如果返回空结果,则该变量将保留其最后一个值。

问题

由于SQL Server中的视图不会每分钟更新一次,因此预计有时在查询运行时,不会添加任何新数据,因此结果将为空。在第一次执行时,查询返回正确的结果。随着循环的继续,预计第二次和第三次尝试均不会返回任何结果,但是在30分钟之后,至少有一个新行添加到该视图可以查看的表中。但是当我的查询在30分钟后运行时,它将获取空结果。

我尝试过的事情

我知道表和视图确实包含数据,因为我测试了这两种不同的方式。我的程序已经运行了6个小时,上次提取的事件数是3个小时。我打开SQL Server Studio,并使用相同的登录凭据运行完全相同的查询,它为我带来了新结果。然后,为确保SQL Server Studio没有执行任何操作,我复制了代码并运行了具有相同代码和相同查询的python程序。这次程序也返回了我预期的结果。在测试这两种方法时,我的程序已经运行了6个小时,完成了它的间隔,然后再次运行查询。但是,该程序没有结果,这是没有意义的。

同样,当我停止程序并重新启动它时。查询的行为符合预期,并获取新结果。

我正在使用python中的日志记录库进行调试。我注意到该程序最终确实会获取新结果,但是会长时间延迟获取它们。令我感到困惑的是,为什么当新运行的其他脚本或程序可以看到数据时,程序却看不到数据。是因为程序已运行6个小时或更长时间导致此问题吗?可能是因为多次执行完全相同的查询,所以将缓存的结果返回给我了吗?为什么系统不知道缓存结果不再有效?

对此有任何帮助,感激不尽!

# My code in the thread

while not self.shutdown_flag.is_set():
    # SQL Query that pulls incident
    sql_query = '''
                    select varc.EventNumber
                    from vw_Events varc (nolock)
                    where varc.CompanyNumber in (
                            ''' + string_of_cust_numbers + '''
                    )
                    and varc.bCommented = 0
                    and varc.EventNumber > ''' + str(last_known_inc_number) + '''
                    and varc.InsertTimeStampGMT >= GETDATE() - 1    -- Need to look at the Added to Queue value rather than when the incident was generated
                    order by varc.EventNumber
                    '''
    exec_msg = 'Querying the SQL Server database to fetch event numbers from live queue'
    exception_msg = 'Queue Fetching Query Execution Failed!'

    query_results = self.db_util.executeASQL(sql_cursor, sql_query, 'INFO', exec_msg, exception_msg)

    if query_results is None:
        logging.critical('Queue Fetcher query had some issue. Investigate. Terminating program')
        return
    else:
        logging.info('Fetched Queue: {}'.format(query_results))

    # Check if the query returned any results and then add to queue
    if query_results:
        for row in query_results:
            my_queue.put(
                int(row[0]))  # Adds the first element which is going to be the incident number in the queue one by one

    # TODO Need to add Queue size checks over here

    # Update last incident number which will be used to fetch only the new incident numbers next time
    if query_results:  # This checks if the results list is empty
        last_known_inc_number = query_results.pop()[0]  # Last entry in results, First element in the tuple

    # Constant Time Interval Gap - 1 minutes for now
    logging.debug('Last Known Inc Number: {}'.format(last_known_inc_number))
    logging.info('Sleeping for 10 minutes')
    time.sleep(600)



# Custom SQL execute function defined in other file
def executeASQL(self, db_cursor, sql_query, loglevel, exec_msg, exception_msg):
    '''
    This function is a wrapper around ASQL execute query to make the code more readable
    :param db_cursor: SQL Cursor object
    :param sql_query: String - sql query to execute
    :param loglevel: String - Logging level for execution message
    :param exec_msg: String - Logging message during execution
    :param exception_msg: String - Logging message if an exception arises
    :return: Query results if succeeded else None
    '''

    try:
        self.loglevel_dict.get(loglevel, 'DEBUG')(exec_msg)
        db_cursor.execute(sql_query)

        results = db_cursor.fetchall()

        return results

    except pyodbc.Error as err:
        self.loglevel_dict.get(loglevel, 'EXCEPTION')(exception_msg)
        # logging.exception('Execution of ASQL Query to determine SIP failed')

        return None

实际结果 提取的队列日志显示一个空列表-> [] 即使视图确实具有数据,因为当我们使用另一个python程序运行相同的查询时,它也会返回结果

预期结果 提取的队列日志应提取新数据-> [1,2,3]

0 个答案:

没有答案