Serverless部署DynamoDB报错:已删GSI仍无法更新投影类型?
我之前用Serverless管理DynamoDB表时也踩过这个一模一样的坑,完全懂你的困惑!明明手动删了GSI,为什么deploy还是报错?这背后主要是CloudFormation状态漂移的问题,下面给你拆解原因和正确的操作步骤:
为什么会出现这个报错?
Serverless框架底层依赖AWS CloudFormation来跟踪基础设施的状态。当你手动在AWS控制台删除GSI后,CloudFormation的栈记录里依然保留着这个GSI的存在信息——它并不知道你已经手动修改了实际资源。所以当你执行sls deploy时,CloudFormation会尝试按照它记录的状态去更新这个“不存在”的GSI,自然就抛出了Cannot update GSI's properties other than Provisioned Throughput的错误。
还有一种小概率情况:DynamoDB的GSI删除是异步操作,你在控制台看到删除成功,但AWS内部可能还在完成清理流程,不过这种情况持续时间很短,核心问题还是CloudFormation的状态不一致。
正确的操作方式
第一步:确保Serverless配置已移除GSI
先检查你的serverless.yml,确认那个要删除的GSI的所有配置代码(包括GlobalSecondaryIndexes下的名称、键、投影配置等)已经完全删除,避免后续部署时再次触发相关逻辑。
第二步:修复CloudFormation的状态漂移
这是解决当前报错的核心步骤,要让CloudFormation的记录和实际资源状态同步:
- 登录AWS控制台,找到Serverless部署对应的CloudFormation栈(栈名通常是
你的服务名-阶段名-区域) - 进入栈的漂移检测页面,点击「执行漂移检测」
- 检测完成后,找到标记为「已漂移」的GSI资源(就是你手动删除的那个)
- 选择「修复漂移」,按照提示将CloudFormation的状态同步为资源已删除
- 完成后再执行
sls deploy,报错就会消失了
以后修改GSI的正确流程(避免再踩坑)
因为DynamoDB确实不支持直接更新GSI的投影类型,所以正确的修改方式是:
- 在
serverless.yml中定义一个全新名称的GSI,配置好你需要的新投影类型 - 执行
sls deploy,让CloudFormation创建这个新GSI(此时旧GSI还存在,数据会同步到新GSI) - 等新GSI的状态变为「ACTIVE」(数据同步完成)后,再在配置中删除旧GSI的代码
- 再次执行
sls deploy,CloudFormation会自动删除旧的GSI
极端情况的下策(谨慎使用)
如果你的表数据可以备份并重新导入,也可以先执行sls remove删除整个表(务必先备份数据!),修改配置后重新sls deploy创建新表和正确的GSI。但这个方法会导致数据丢失,只有在其他方法都无效时才考虑。
内容的提问来源于stack exchange,提问作者Joey Yi Zhao

