boto3 KeyConditionExpressions每个键只能包含一个条件

时间:2017-03-07 03:42:31

标签: boto3

我在使用以下代码时遇到问题。最难理解的是,当很多查询操作在很短的时间间隔内发生时,表达总是发生的 表现如下:

2017-03-05 15:03:59,053 data_sync_worker.py[line:83] ERROR An error occurred (ValidationException) when calling the Query operation: KeyConditionExpressions must only contain one condition per key
ClientError: An error occurred (ValidationException) when calling the Query operation: KeyConditionExpressions must only contain one condition per key

这是我的代码:

response = self.record_tb.query(
                KeyConditionExpression=Key(self.partition_key).eq(user_id) &
                Key(self.sort_key).between(
                    begin_time+Decimal(CACHE_TIMESTAMP_MIN_STEP),
                    endtime))

这是表键架构:

"KeySchema": [
    {
        "KeyType": "HASH", 
        "AttributeName": "user_id"
    }, 
    {
        "KeyType": "RANGE", 
        "AttributeName": "timestamp"
    }
]

那么,有没有人遇到过这个?

2 个答案:

答案 0 :(得分:1)

@killthrush 的回答结果证明是我们出现此错误的原因。基本上,正如他所指出的,boto3 似乎不是线程安全的,我们从多个并发线程读取 s3。

如果您正在寻找快速解决方案,我在他提供的工作链接中找到了@pedros007 的评论。基本上,当您设置 boto3 s3 客户端时,将 max_pool_connecetions 设置为您正在运行的工作人员数量,到目前为止我们已经停止收到 ValidationException 错误。

# code from pedros007
num_threads = 16
cfg = botocore.config.Config(max_pool_connections=num_threads)
client = boto3.client("s3", config=cfg)
futures = {}
with ThreadPoolExecutor(max_workers = num_threads) as executor:
    for key in keys:
        f = executor.submit(my_head_object_function, key, client)
        futures[f] = key

其他人建议在每个线程中开始一个新会话,我已经尝试过,并且确实有效,但性能受到很大影响。与上述方法性能相同。

答案 1 :(得分:0)

上面的错误消息可能是由于代码中的查询格式错误而引起的,对于许多人来说,这是一个合理的解释。但是,我已经确认,如果您使用共享的query资源并在许多负载下运行多个线程或任务来运行dynamodb Table,也会收到此神秘且极具误导性的错误消息。我认为这就是OP案中正在发生的事情。我已经看到boto3 1.9.82和pathos库以及python 3.6中的asyncio都发生了这种情况。

从长远来看,这是many of us have suspected的东西-boto3即使在实践中经常起作用,也不是完全线程安全的。

在这种特殊情况下,我怀疑在查询构建过程中某些状态会损坏,从而使实际上提交给服务端点的查询无效。我无法按需复制此内容。再次重新运行相同的代码似乎总是可行。可以使用botocore记录器捕获发送到AWS的实际有效负载-这将证明我的理论。但是,要捕获如此大量的日志对我来说真的是很昂贵的,所以我只是停止使用共享的Table资源,并且停止看到错误。