在azure存储表中同时访问两次冲突

时间:2019-01-29 21:14:35

标签: python azure azure-storage

我一直在运行脚本来从Azure存储表(例如this作为参考)中检索数据,并将其从同一存储帐户复制到另一个表中而不会出现问题。

现在,当我尝试访问后一个表以运行一些计算并将其从同一存储帐户复制到另一个表中时,问题就来了。该脚本返回以下错误:

AzureConflictHttpError: Conflict
{"odata.error":{"code":"EntityAlreadyExists","message":{"lang":"en-US","value":"The specified entity already exists.\nRequestId:57d9b721-6002-012d-3d0c-b88bef000000\nTime:2019-01-29T19:55:53.5984026Z"}}}

但是,与此同时,我先前运行的代码也停止打印相同的错误,即使没有代码运行也不会再次启动,从而一遍又一遍地返回上一个错误。

有什么方法可以多次访问Azure存储中的同一API?

更新

添加源代码,很抱歉以前没有这样做。基本上,我并行运行的2个代码相同,但过滤器不同;在这个数据库中,我从表1(每秒有一行)中获取数据,并且将每分钟的平均数量添加到表2中,而在另一个脚本中,我从该表中获取数据2将每分钟的这些行平均为另一个表3中的5分钟的平均行,因此基本更改了一些参数,但是代码基本相同。

会有第三个脚本,与这两个脚本略有不同,但是将以表2为输入源,运行其他计算并将结果每分钟粘贴到以后的表4中每分钟的新行中,因此总的来说,我的想法是是要同时具有多个表的多个条目以构建新的特定表。

import datetime
import time
from azure.storage.table import TableService, Entity

delta_time = '00:01:00'
retrieve_time = '00:10:00'
start_time = '08:02:00'
utc_diff = 3

table_service = TableService(account_name='xxx', account_key='yyy')

while True:
    now_time = datetime.datetime.now().strftime("%H:%M:%S") 
    now_date = datetime.datetime.now().strftime("%d-%m-%Y")
    hour = datetime.datetime.now().hour

    if hour >= 21:
        now_date = (datetime.datetime.now() + datetime.timedelta(days=1)).strftime("%d-%m-%Y")

    retrieve_max = (datetime.datetime.now() + datetime.timedelta(hours=utc_diff)+ datetime.timedelta(minutes=-10)).strftime("%H:%M:%S")

    start_diff = datetime.datetime.strptime(now_time, '%H:%M:%S') - datetime.datetime.strptime(start_time, '%H:%M:%S') + datetime.timedelta(hours=utc_diff)
    if start_diff.total_seconds() > 0:

        query = "PartitionKey eq '"+str(now_date)+"' and RowKey ge '"+str(retrieve_max)+"'"
        tasks=table_service.query_entities('Table1',query)
        iqf_0 = []

        for task in tasks:
            if task.Name == "IQF_0":
                iqf_0.append([task.RowKey, task.Area])  

        last_time = iqf_0[len(iqf_0)-1][0]
        time_max = datetime.datetime.strptime(last_time, '%H:%M:%S') - datetime.datetime.strptime(delta_time, '%H:%M:%S') #+ datetime.timedelta(hours=utc_diff)
        area = 0.0
        count = 0
        for i in range(len(iqf_0)-1, -1, -1):
            diff = datetime.datetime.strptime(last_time, '%H:%M:%S') - datetime.datetime.strptime(iqf_0[i][0], '%H:%M:%S')
            if diff.total_seconds() < 60:
                area += iqf_0[i][1]
                count += 1
            else: 
                break
        area_average = area/count

        output_row = Entity()
        output_row.PartitionKey = now_date
        output_row.RowKey = last_time
        output_row.Name = task.Name
        output_row.Area = area_average
        table_service.insert_entity('Table2', output_row)

        date_max = datetime.datetime.now() + datetime.timedelta(days=-1)
        date_max = date_max.strftime("%d-%m-%Y")
        query = "PartitionKey eq '"+str(date_max)+"' and RowKey ge '"+str(retrieve_max)+"'"
        tasks=table_service.query_entities('Table2',query)

        for task in tasks:
            diff = datetime.datetime.strptime(now_time, '%H:%M:%S') - datetime.datetime.strptime(task.RowKey, '%H:%M:%S') + datetime.timedelta(hours=utc_diff)
            print(i, datetime.datetime.strptime(now_time, '%H:%M:%S'), datetime.datetime.strptime(task.RowKey, '%H:%M:%S'), diff.total_seconds())
            if task.PartitionKey == date_max and diff.total_seconds()>0:
                table_service.delete_entity('Table2', task.PartitionKey, task.RowKey)

        time.sleep(60 - time.time() % 60)

1 个答案:

答案 0 :(得分:1)

听起来好像您正在运行两个代码以将同一Azure Storage Accout中的数据同时从表1复制到表2,再复制到表3。根据我的经验,该问题通常是由于同时写入数据记录(表实体)或对现有实体使用不正确的方法导致的,这是写入时的资源竞争问题。

这是常见的表格服务错误,您可以在here上找到它。 enter image description here

还有一个文档Inserting and Updating Entities,它解释了功能Insert EntityUpdate EntityMerge EntityInsert Or Merge Entity和{ {1}}。

现在,您的代码尚未为我们共享。考虑所有可能的情况,有三种解决此问题的解决方案。

  1. 依次运行两个代码,以便在不同表之间复制数据,而不是同时复制。

  2. 使用正确的功能来更新现有实体的数据,您可以参考上面的文档以及类似的SO线程Add or replace entity in Azure Table Storage

  3. 对表实体的唯一主键使用全局锁,以避免在两个代码中同时操作同一表实体。