Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Amazon web services 无法使用CloudFormation将GSI添加到DynamoDB表_Amazon Web Services_Amazon Dynamodb_Amazon Cloudformation - Fatal编程技术网

Amazon web services 无法使用CloudFormation将GSI添加到DynamoDB表

Amazon web services 无法使用CloudFormation将GSI添加到DynamoDB表,amazon-web-services,amazon-dynamodb,amazon-cloudformation,Amazon Web Services,Amazon Dynamodb,Amazon Cloudformation,我有一个现有的DynamoDB表,它被定义为CloudFormation堆栈的一部分。根据定义,GlobalSecondaryIndex属性不需要替换。它甚至详细说明了以下注意事项 您可以不间断地删除或添加一个全局辅助索引 以及以下内容 如果更新表以包含新的全局二级索引,则AWS CloudFormation启动索引创建,然后继续 堆栈更新。AWS CloudFormation不会等待索引恢复 完成创建,因为回填阶段可能需要很长时间, 取决于桌子的大小 但是,实际上,当我尝试执行更新时,会收到以

我有一个现有的DynamoDB表,它被定义为CloudFormation堆栈的一部分。根据定义,GlobalSecondaryIndex属性不需要替换。它甚至详细说明了以下注意事项

您可以不间断地删除或添加一个全局辅助索引

以及以下内容

如果更新表以包含新的全局二级索引,则AWS CloudFormation启动索引创建,然后继续 堆栈更新。AWS CloudFormation不会等待索引恢复 完成创建,因为回填阶段可能需要很长时间, 取决于桌子的大小

但是,实际上,当我尝试执行更新时,会收到以下错误消息:

CloudFormation cannot update a stack when a custom-named resource requires replacing. Rename mytablename and update the stack again.
由于我添加了一个使用新属性的GSI,我不得不修改AttributeDefinitions,这表示它确实需要替换。然而,即使我尝试添加一个GSI,其中只有AttributeDefinitions中定义的现有属性,我仍然会收到相同的错误消息

以下是我的表的原始CFN定义的片段:

{
  "myTable": {
    "Type": "AWS::DynamoDB::Table",
    "Properties": {
      "TableName": "mytablename",
      "AttributeDefinitions": [
        {
          "AttributeName": "entryId",
          "AttributeType": "S"
        },
        {
          "AttributeName": "entryName",
          "AttributeType": "S"
        },
        {
          "AttributeName": "appId",
          "AttributeType": "S"
        }
      ],
      "KeySchema": [
        {
          "KeyType": "HASH",
          "AttributeName": "entryId"
        },
        {
          "KeyType": "RANGE",
          "AttributeName": "entryName"
        }
      ],
      "ProvisionedThroughput": {
        "ReadCapacityUnits": {
          "Ref": "readThroughput"
        },
        "WriteCapacityUnits": {
          "Ref": "writeThroughput"
        }
      },
      "GlobalSecondaryIndexes": [
        {
            "IndexName": "appId-index",
          "KeySchema": [
            {
              "KeyType": "HASH",
              "AttributeName": "appId"
            }
          ],
          "Projection": {
            "ProjectionType": "KEYS_ONLY"
          },
          "ProvisionedThroughput": {
            "ReadCapacityUnits": {
              "Ref": "readThroughput"
            },
            "WriteCapacityUnits": {
              "Ref": "writeThroughput"
            }
          }
        }
      ]
    }
  }
}
以下是我想要更新的内容:

{
  "myTable": {
    "Type": "AWS::DynamoDB::Table",
    "Properties": {
      "TableName": "mytablename",
      "AttributeDefinitions": [
        {
          "AttributeName": "entryId",
          "AttributeType": "S"
        },
        {
          "AttributeName": "entryName",
          "AttributeType": "S"
        },
        {
          "AttributeName": "appId",
          "AttributeType": "S"
        },
        {
          "AttributeName": "userId",
          "AttributeType": "S"
        }
      ],
      "KeySchema": [
        {
          "KeyType": "HASH",
          "AttributeName": "entryId"
        },
        {
          "KeyType": "RANGE",
          "AttributeName": "entryName"
        }
      ],
      "ProvisionedThroughput": {
        "ReadCapacityUnits": {
          "Ref": "readThroughput"
        },
        "WriteCapacityUnits": {
          "Ref": "writeThroughput"
        }
      },
      "GlobalSecondaryIndexes": [
        {
            "IndexName": "appId-index",
          "KeySchema": [
            {
              "KeyType": "HASH",
              "AttributeName": "appId"
            }
          ],
          "Projection": {
            "ProjectionType": "KEYS_ONLY"
          },
          "ProvisionedThroughput": {
            "ReadCapacityUnits": {
              "Ref": "readThroughput"
            },
            "WriteCapacityUnits": {
              "Ref": "writeThroughput"
            }
          }
        },
        {
          "IndexName": "userId-index",
          "KeySchema": [
            {
              "KeyType": "HASH",
              "AttributeName": "userId"
            }
          ],
          "Projection": {
            "ProjectionType": "KEYS_ONLY"
          },
          "ProvisionedThroughput": {
            "ReadCapacityUnits": {
              "Ref": "readThroughput"
            },
            "WriteCapacityUnits": {
              "Ref": "writeThroughput"
            }
          }
        }
      ]
    }
  }
}

但是,正如我前面提到的,即使我没有在AttributeDefinitions中定义userId,并且在新的GSI定义中使用现有属性,它也不会工作,并且会失败,并显示相同的错误消息。

我今天也遇到了相同的错误,并从Amazon技术支持部门得到了答案。问题是您提供了一个TableName字段。CloudFormation希望负责为您的表命名。显然,当您为它们提供自己的名称时,这就是您在替换表的更新中遇到的错误(不确定为什么需要替换,但文档是这么说的)


对我来说,这使得CloudFormation对于维护我的DynamoDB表毫无用处。我必须内置配置,以便我的代码能够动态地告诉我CloudFormation为我生成的随机表名。

AWS支持部门对我的回应FWIW:

解决问题
  • 将数据从表导出到s3
  • 使用添加了gsi的新表名(tablename2)更新堆栈
    • 注意,这会丢失所有当前条目,因此一定要先备份到s3
  • 再次更新堆栈,返回使用dynamodb表中的tablename1
  • 从s3导入数据这可以通过使用数据管道来简化,请参见
  • 优点是,应用程序代码可以继续使用固定名称。但是更新堆栈两次并导出/导入数据需要一些工作才能在自定义脚本中实现自动化

    解决办法B
  • 备份数据
  • 让我们来命名这个表
  • 使用AWS SDK检索表名,方法是通过按逻辑id描述堆栈资源获取名称,然后从输出中获取表名 虽然我认为这避免了额外的堆栈更新(仍然认为需要导出/导入数据),但缺点是在代码中进行网络调用以获取表名。看见 *


    同样,这是一个众所周知的问题,支持正在推动服务团队前进,因为我们知道这是一个非常常见的用例和难点。在进行生产测试之前,请在测试环境中尝试解决方法。

    备份DynamoDB中的所有数据,然后,如果您使用的是无服务器,请执行以下任一命令:

    个人删除:

    node ./node_modules/serverless/bin/serverless remove
    
    全局删除:

    serverless remove
    
    并通过运行以下命令再次部署它:

    node ./node_modules/serverless/bin/serverless deploy -v
    


    我的设想是,我想通过更改GSI的范围键来更新GSI。
    -首先,您必须删除您正在更新的GSI,还记得删除由于删除GSI而可能不再需要的任何AttributeDefinition,即索引名等。通过CloudFormation上载模板以应用更改。
    -然后将所需的属性和“更新的”GSI添加到模板中。

    问题是如何发生的? 对于我来说,在dynamoDB控制台中手动删除GSI,然后通过cloudformation添加GSI,更新堆栈得到这个错误

    解决方案:删除cloudformation中的GSI,执行更新堆栈,然后添加回GSI,再次执行更新堆栈,工作正常


    猜测cloudformation有自己的缓存,无法判断您在控制台中手动进行的更改。

    我可以确认,当我尝试添加GSI而不更改AttributeDefinitions时,也会发生同样的情况。文件还规定了以下内容:“更新要求:不支持更新。除了以下例外:如果只更新全局辅助索引的已设置吞吐量值,则可以不中断地更新表。您可以不间断地删除或添加一个全局辅助索引。如果在同一更新中同时执行这两项操作(例如,通过更改索引的逻辑ID),则更新将失败。“在亚马逊方面,我不明白的是,云信息如何可能对迪纳摩有用。当然,我想选择一个我命名的表…这对我来说毫无意义。您可以在运行时通过逻辑ID(CFN模板中的名称)从CloudFormation获取表名。如果这样做,您可以将备份的数据还原到新创建的表中吗?“还要记住删除任何可能不再需要的属性定义“,这就是我所缺少的。如果该属性未在gsi中使用,则该属性不应存在于AttributeDefinition中。这对我很有用。自定义表名应该没有问题。如果有相同的问题,我必须先执行
    sls-remove
    ,然后执行
    sls-deploy-v
    ,以获得一个干净的列表:)
    serverless deploy