Azure Blob Storage中Etag乐观锁失效:旧Etag仍可执行SetMetaDataAsync
Azure Blob容器Etag乐观锁未生效?我来帮你排查!
我之前也踩过这个一模一样的坑!你遇到的问题核心原因很明确:你在第二次调用SetMetaDataAsync时,没有显式指定Etag校验的访问条件。Azure Blob存储的乐观锁机制不是自动触发的,必须通过AccessCondition(旧SDK)或BlobRequestConditions(新SDK)明确告诉服务端“只有当Etag匹配我指定的值时,才允许更新”,否则服务端会直接执行更新,完全不做校验。
你可能遗漏的关键代码步骤
看你给出的代码片段,应该是没把旧Etag传入访问条件参数。这里分两种SDK版本给你正确的写法:
旧版SDK(Microsoft.Azure.Storage.Blob)
var blobClient = account.CreateCloudBlobClient(); var container = blobClient.GetContainerReference("你的容器名"); // 先获取容器当前的Etag(第一次操作前) await container.FetchAttributesAsync(); string oldEtag = container.Properties.ETag; // 第一次更新元数据(此时Etag会变更) container.Metadata.Add("key1", "value1"); await container.SetMetadataAsync(); // 第二次更新,这里必须传入旧Etag的校验条件! AccessCondition condition = AccessCondition.GenerateIfMatchCondition(oldEtag); try { container.Metadata["key1"] = "value2"; await container.SetMetadataAsync(condition, null, null); } catch (StorageException ex) { if (ex.RequestInformation.HttpStatusCode == 412) { // 预条件失败,说明Etag不匹配,处理冲突逻辑 Console.WriteLine("元数据已被其他请求修改,乐观锁生效!"); } }
新版SDK(Azure.Storage.Blobs)
如果用的是最新的SDK,API有变化,需要用BlobRequestConditions:
var blobServiceClient = new BlobServiceClient("你的连接字符串"); var containerClient = blobServiceClient.GetBlobContainerClient("你的容器名"); // 获取旧Etag var containerProperties = await containerClient.GetPropertiesAsync(); string oldEtag = containerProperties.ETag.ToString(); // 第一次更新 await containerClient.SetMetadataAsync(new Dictionary<string, string> { {"key1", "value1"} }); // 第二次更新,指定IfMatch条件 var requestConditions = new BlobRequestConditions { IfMatch = new ETag(oldEtag) }; try { await containerClient.SetMetadataAsync(new Dictionary<string, string> { {"key1", "value2"} }, requestConditions); } catch (RequestFailedException ex) { if (ex.Status == 412) { Console.WriteLine("乐观锁触发:元数据已被修改!"); } }
额外要注意的细节
- 确保你校验的是容器的Etag,而不是容器内Blob的Etag——容器和Blob的Etag是完全独立的,互相不影响。
- 当Etag校验失败时,服务端会返回
412 Precondition Failed状态码,一定要捕获这个异常来处理冲突场景,比如提示用户重试或者合并变更。
内容的提问来源于stack exchange,提问作者Justin Self
相关产品推荐
相关产品推荐

