我在使用以下代码时遇到问题。最难理解的是,当很多查询操作在很短的时间间隔内发生时,表达总是发生的 表现如下:
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"
}
]
那么,有没有人遇到过这个?
答案 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
资源,并且停止看到错误。