만료된 항목 및 TTL(Time To Live) 작업
삭제 보류 중인 만료된 항목은 읽기 및 쓰기 작업에서 필터링할 수 있습니다. 이는 만료된 데이터가 더 이상 유효하지 않아 사용해서는 안 되는 시나리오에서 유용합니다. 필터링되지 않은 경우 백그라운드 프로세스에서 삭제될 때까지 읽기 및 쓰기 작업에 계속 표시됩니다.
참고
이러한 항목은 삭제되기 전까지는 여전히 스토리지 및 읽기 비용에 포함됩니다.
TTL 삭제는 DynamoDB Streams에서 식별할 수 있지만 삭제가 발생한 리전에서만 식별할 수 있습니다. 글로벌 테이블 리전에 복제된 TTL 삭제는 삭제가 복제되는 리전의 DynamoDB 스트림에서 식별할 수 없습니다.
읽기 작업에서 만료된 항목 필터링
스캔 및 쿼리와 같은 읽기 작업의 경우 필터 표현식을 사용하여 삭제 보류 중인 만료된 항목을 필터링할 수 있습니다. 다음 코드 스니펫에서 볼 수 있듯이 필터 표현식은 TTL 시간이 현재 시간과 같거나 그보다 전인 항목을 필터링할 수 있습니다. 예를 들어, Python SDK 코드에는 현재 시간을 변수(now
)로 가져와서 epoch 시간 형식의 경우 int
로 변환하는 할당 문이 포함되어 있습니다.
다음 코드 예제는 TTL 항목을 쿼리하는 방법을 보여줍니다.
- Java
-
- SDK for Java 2.x
-
필터링된 표현식을 쿼리하여 DynamoDB 테이블에서 TTL 항목을 수집합니다.
import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import software.amazon.awssdk.services.dynamodb.model.DynamoDbException; import software.amazon.awssdk.services.dynamodb.model.QueryRequest; import software.amazon.awssdk.services.dynamodb.model.QueryResponse; import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException; import software.amazon.awssdk.utils.ImmutableMap; import java.util.Map; import java.util.Optional; // Get current time in epoch second format (comparing against expiry attribute) final long currentTime = System.currentTimeMillis() / 1000; // A string that contains conditions that DynamoDB applies after the Query operation, but before the data is returned to you. final String keyConditionExpression = "#pk = :pk"; // The condition that specifies the key values for items to be retrieved by the Query action. final String filterExpression = "#ea > :ea"; final Map<String, String> expressionAttributeNames = ImmutableMap.of( "#pk", "primaryKey", "#ea", "expireAt"); final Map<String, AttributeValue> expressionAttributeValues = ImmutableMap.of( ":pk", AttributeValue.builder().s(primaryKey).build(), ":ea", AttributeValue.builder().s(String.valueOf(currentTime)).build() ); final QueryRequest request = QueryRequest.builder() .tableName(tableName) .keyConditionExpression(keyConditionExpression) .filterExpression(filterExpression) .expressionAttributeNames(expressionAttributeNames) .expressionAttributeValues(expressionAttributeValues) .build(); try (DynamoDbClient ddb = DynamoDbClient.builder() .region(region) .build()) { final QueryResponse response = ddb.query(request); System.out.println(tableName + " Query operation with TTL successful. Request id is " + response.responseMetadata().requestId()); // Print the items that are not expired for (Map<String, AttributeValue> item : response.items()) { System.out.println(item.toString()); } } catch (ResourceNotFoundException e) { System.err.format("Error: The Amazon DynamoDB table \"%s\" can't be found.\n", tableName); System.exit(1); } catch (DynamoDbException e) { System.err.println(e.getMessage()); System.exit(1); } System.exit(0);
-
API 세부 정보는 AWS SDK for Java 2.x API 참조의 Query를 참조하십시오.
-
- JavaScript
-
- SDK for JavaScript (v3)
-
import { DynamoDBClient, QueryCommand } from "@aws-sdk/client-dynamodb"; import { marshall, unmarshall } from "@aws-sdk/util-dynamodb"; async function queryDynamoDBItems(tableName, region, primaryKey) { const client = new DynamoDBClient({ region: region, endpoint: `https://dynamodb.${region}.amazonaws.com` }); const currentTime = Math.floor(Date.now() / 1000); const params = { TableName: tableName, KeyConditionExpression: "#pk = :pk", FilterExpression: "#ea > :ea", ExpressionAttributeNames: { "#pk": "primaryKey", "#ea": "expireAt" }, ExpressionAttributeValues: marshall({ ":pk": primaryKey, ":ea": currentTime }) }; try { const { Items } = await client.send(new QueryCommand(params)); Items.forEach(item => { console.log(unmarshall(item)) }); return Items; } catch (err) { console.error(`Error querying items: ${err}`); throw err; } } //enter your own values here queryDynamoDBItems('your-table-name', 'your-partition-key-value');
-
API 세부 정보는 AWS SDK for JavaScript API 참조의 Query를 참조하십시오.
-
- Python
-
- SDK for Python(Boto3)
-
import boto3 from datetime import datetime def query_dynamodb_items(table_name, partition_key): """ :param table_name: Name of the DynamoDB table :param partition_key: :return: """ try: # Initialize a DynamoDB resource dynamodb = boto3.resource('dynamodb', region_name='us-east-1') # Specify your table table = dynamodb.Table(table_name) # Get the current time in epoch format current_time = int(datetime.now().timestamp()) # Perform the query operation with a filter expression to exclude expired items # response = table.query( # KeyConditionExpression=boto3.dynamodb.conditions.Key('partitionKey').eq(partition_key), # FilterExpression=boto3.dynamodb.conditions.Attr('expireAt').gt(current_time) # ) response = table.query( KeyConditionExpression=dynamodb.conditions.Key('partitionKey').eq(partition_key), FilterExpression=dynamodb.conditions.Attr('expireAt').gt(current_time) ) # Print the items that are not expired for item in response['Items']: print(item) except Exception as e: print(f"Error querying items: {e}") # Call the function with your values query_dynamodb_items('Music', 'your-partition-key-value')
-
API 세부 정보는 AWS SDK for Python (Boto3) API 참조의 Query를 참조하십시오.
-
만료된 항목에 조건부 쓰기
조건식을 사용하면 만료된 항목에 대한 쓰기를 방지할 수 있습니다. 아래 코드 스니펫은 만료 시간이 현재 시간보다 큰지를 확인하는 조건부 업데이트입니다. true인 경우 쓰기 작업이 계속됩니다.
다음 코드 예제는 항목의 TTL을 조건부로 업데이트하는 방법을 보여줍니다.
- Java
-
- SDK for Java 2.x
-
package com.amazon.samplelib.ttl; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; import software.amazon.awssdk.services.dynamodb.model.AttributeValue; import software.amazon.awssdk.services.dynamodb.model.DynamoDbException; import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException; import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest; import software.amazon.awssdk.services.dynamodb.model.UpdateItemResponse; import software.amazon.awssdk.utils.ImmutableMap; import java.util.Map; import java.util.Optional; public class UpdateTTLConditional { public static void main(String[] args) { final String usage = """ Usage: <tableName> <primaryKey> <sortKey> <newTtlAttribute> <region> Where: tableName - The Amazon DynamoDB table being queried. primaryKey - The name of the primary key. Also known as the hash or partition key. sortKey - The name of the sort key. Also known as the range attribute. newTtlAttribute - New attribute name (as part of the update command) region (optional) - The AWS region that the Amazon DynamoDB table is located in. (Default: us-east-1) """; // Optional "region" parameter - if args list length is NOT 3 or 4, short-circuit exit. if (!(args.length == 4 || args.length == 5)) { System.out.println(usage); System.exit(1); } final String tableName = args[0]; final String primaryKey = args[1]; final String sortKey = args[2]; final String newTtlAttribute = args[3]; Region region = Optional.ofNullable(args[4]).isEmpty() ? Region.US_EAST_1 : Region.of(args[4]); // Get current time in epoch second format final long currentTime = System.currentTimeMillis() / 1000; // Calculate expiration time 90 days from now in epoch second format final long expireDate = currentTime + (90 * 24 * 60 * 60); // An expression that defines one or more attributes to be updated, the action to be performed on them, and new values for them. final String updateExpression = "SET newTtlAttribute = :val1"; // A condition that must be satisfied in order for a conditional update to succeed. final String conditionExpression = "expireAt > :val2"; final ImmutableMap<String, AttributeValue> keyMap = ImmutableMap.of("primaryKey", AttributeValue.fromS(primaryKey), "sortKey", AttributeValue.fromS(sortKey)); final Map<String, AttributeValue> expressionAttributeValues = ImmutableMap.of( ":val1", AttributeValue.builder().s(newTtlAttribute).build(), ":val2", AttributeValue.builder().s(String.valueOf(expireDate)).build() ); final UpdateItemRequest request = UpdateItemRequest.builder() .tableName(tableName) .key(keyMap) .updateExpression(updateExpression) .conditionExpression(conditionExpression) .expressionAttributeValues(expressionAttributeValues) .build(); try (DynamoDbClient ddb = DynamoDbClient.builder() .region(region) .build()) { final UpdateItemResponse response = ddb.updateItem(request); System.out.println(tableName + " UpdateItem operation with conditional TTL successful. Request id is " + response.responseMetadata().requestId()); } catch (ResourceNotFoundException e) { System.err.format("Error: The Amazon DynamoDB table \"%s\" can't be found.\n", tableName); System.exit(1); } catch (DynamoDbException e) { System.err.println(e.getMessage()); System.exit(1); } System.exit(0); } }
-
API 세부 정보는 AWS SDK for Java 2.x API 참조의 UpdateItem을 참조하십시오.
-
- JavaScript
-
- SDK for JavaScript (v3)
-
조건을 사용하여 테이블의 기존 DynamoDB 항목에서 TTL을 업데이트합니다.
import { DynamoDBClient, UpdateItemCommand } from "@aws-sdk/client-dynamodb"; import { marshall, unmarshall } from "@aws-sdk/util-dynamodb"; const updateDynamoDBItem = async (tableName, region, partitionKey, sortKey, newAttribute) => { const client = new DynamoDBClient({ region: region, endpoint: `https://dynamodb.${region}.amazonaws.com` }); const currentTime = Math.floor(Date.now() / 1000); const params = { TableName: tableName, Key: marshall({ artist: partitionKey, album: sortKey }), UpdateExpression: "SET newAttribute = :newAttribute", ConditionExpression: "expireAt > :expiration", ExpressionAttributeValues: marshall({ ':newAttribute': newAttribute, ':expiration': currentTime }), ReturnValues: "ALL_NEW" }; try { const response = await client.send(new UpdateItemCommand(params)); const responseData = unmarshall(response.Attributes); console.log("Item updated successfully: ", responseData); return responseData; } catch (error) { if (error.name === "ConditionalCheckFailedException") { console.log("Condition check failed: Item's 'expireAt' is expired."); } else { console.error("Error updating item: ", error); } throw error; } }; // Enter your values here updateDynamoDBItem('your-table-name', "us-east-1",'your-partition-key-value', 'your-sort-key-value', 'your-new-attribute-value');
-
API 세부 정보는 AWS SDK for JavaScript API 참조의 UpdateItem을 참조하십시오.
-
- Python
-
- SDK for Python(Boto3)
-
import boto3 from datetime import datetime, timedelta from botocore.exceptions import ClientError def update_dynamodb_item(table_name, region, primary_key, sort_key, ttl_attribute): """ Updates an existing record in a DynamoDB table with a new or updated TTL attribute. :param table_name: Name of the DynamoDB table :param region: AWS Region of the table - example `us-east-1` :param primary_key: one attribute known as the partition key. :param sort_key: Also known as a range attribute. :param ttl_attribute: name of the TTL attribute in the target DynamoDB table :return: """ try: dynamodb = boto3.resource('dynamodb', region_name=region) table = dynamodb.Table(table_name) # Generate updated TTL in epoch second format updated_expiration_time = int((datetime.now() + timedelta(days=90)).timestamp()) # Define the update expression for adding/updating a new attribute update_expression = "SET newAttribute = :val1" # Define the condition expression for checking if 'expireAt' is not expired condition_expression = "expireAt > :val2" # Define the expression attribute values expression_attribute_values = { ':val1': ttl_attribute, ':val2': updated_expiration_time } response = table.update_item( Key={ 'primaryKey': primary_key, 'sortKey': sort_key }, UpdateExpression=update_expression, ConditionExpression=condition_expression, ExpressionAttributeValues=expression_attribute_values ) print("Item updated successfully.") return response['ResponseMetadata']['HTTPStatusCode'] # Ideally a 200 OK except ClientError as e: if e.response['Error']['Code'] == "ConditionalCheckFailedException": print("Condition check failed: Item's 'expireAt' is expired.") else: print(f"Error updating item: {e}") except Exception as e: print(f"Error updating item: {e}") # replace with your values update_dynamodb_item('your-table-name', 'us-east-1', 'your-partition-key-value', 'your-sort-key-value', 'your-ttl-attribute-value')
-
API 세부 정보는 AWS SDK for Python (Boto3) API 참조의 UpdateItem를 참조하십시오.
-
DynamoDB Streams에서 삭제된 항목 식별
스트림 레코드에는 사용자 ID 필드 Records[<index>].userIdentity
가 포함되어 있습니다. TTL 프로세스에 의해 삭제된 항목은 다음 필드를 갖습니다.
Records[<index>].userIdentity.type "Service" Records[<index>].userIdentity.principalId "dynamodb.amazonaws.com"
다음 JSON은 단일 스트림 레코드의 해당 부분을 보여줍니다.
"Records": [ { ... "userIdentity": { "type": "Service", "principalId": "dynamodb.amazonaws.com" } ... } ]