DynamoDB y bloqueo positivo con el número de versión
El bloqueo optimista es una estrategia para asegurarse de que el elemento del lado del cliente que se va a actualizar (o eliminar) sea el mismo que figura en Amazon DynamoDB. Si utiliza esta estrategia, las escrituras en su base de datos se protegen contra posibles sobrescrituras de otros y viceversa.
Con el bloqueo optimista, cada elemento tiene un atributo que actúa como número de versión. Si recupera un elemento de una tabla, la aplicación registra el número de versión de ese elemento. Puede actualizar el elemento, pero solo si el número de versión del lado del servidor no ha cambiado. Si no hay una coincidencia de versión, significa que alguien más ha modificado el elemento antes que usted. El intento de actualización falla porque tiene una versión obsoleta del elemento. Si esto ocurre, intente recuperar el elemento y actualizarlo. El bloqueo optimista impide que sobrescriba accidentalmente los cambios realizados por otras personas. También impide que otras personas sobrescriban accidentalmente sus cambios.
Si bien puede implementar su propia estrategia de bloqueo positivo, AWS SDK for Java proporciona la anotación @DynamoDBVersionAttribute
. En la clase de mapeo de la tabla, debe designar una propiedad en la que se almacenará el número de versión y marcarla con esta anotación. Al guardar un objeto, el elemento correspondiente de la tabla de DynamoDB tendrá un atributo en el que se almacenará el número de versión. DynamoDBMapper
asigna un número de versión la primera vez que se guarda el objeto y aumenta automáticamente este número de versión cada vez que se actualiza el elemento. Las solicitudes de actualización o eliminación solamente se llevan a cabo si la versión del objeto en el lado del cliente coincide con el número de versión del elemento correspondiente en la tabla de DynamoDB.
ConditionalCheckFailedException
se lanza si:
-
Utiliza el bloqueo optimista con
@DynamoDBVersionAttribute
y el valor de versión en el servidor es distinto del valor en el lado del cliente. -
Especifique sus propias limitaciones condicionales al guardar los datos utilizando
DynamoDBMapper
conDynamoDBSaveExpression
y estas limitaciones han fallado.
nota
-
Las tablas globales de DynamoDB usan una reconciliación del tipo "prevalece el último escritor" entre las actualizaciones simultáneas. Si usa tablas globales, prevalecerá la política del último escritor. Por tanto, en este caso, la estrategia de bloqueo no funciona según lo previsto.
-
Las operaciones de escritura transaccional
DynamoDBMapper
no admiten expresiones de anotación y condición@DynamoDBVersionAttribute
en el mismo objeto. Si un objeto en una escritura transacciones se anota con@DynamoDBVersionAttribute
y también tiene una expresión de condición, se producirá una SdkClientException.
Por ejemplo, en el siguiente código Java se define una clase CatalogItem
que tiene varias propiedades. La propiedad Version
está etiquetada con la anotación @DynamoDBVersionAttribute
.
ejemplo
@DynamoDBTable(tableName="ProductCatalog") public class CatalogItem { private Integer id; private String title; private String ISBN; private Set<String> bookAuthors; private String someProp; private Long version; @DynamoDBHashKey(attributeName="Id") public Integer getId() { return id; } public void setId(Integer Id) { this.id = Id; } @DynamoDBAttribute(attributeName="Title") public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } @DynamoDBAttribute(attributeName="ISBN") public String getISBN() { return ISBN; } public void setISBN(String ISBN) { this.ISBN = ISBN;} @DynamoDBAttribute(attributeName = "Authors") public Set<String> getBookAuthors() { return bookAuthors; } public void setBookAuthors(Set<String> bookAuthors) { this.bookAuthors = bookAuthors; } @DynamoDBIgnore public String getSomeProp() { return someProp;} public void setSomeProp(String someProp) {this.someProp = someProp;} @DynamoDBVersionAttribute public Long getVersion() { return version; } public void setVersion(Long version) { this.version = version;} }
Puede aplicar la anotación @DynamoDBVersionAttribute
a los tipos que admiten valores null; estos están disponibles en las clases encapsuladoras primitivas que proporcionan un tipo que admite valores null, tales como Long
e Integer
.
El bloqueo optimista afecta a los siguientes métodos de DynamoDBMapper
como se indica a continuación:
-
save
: para un elemento nuevo,DynamoDBMapper
asigna un número de versión inicial de 1. Si recupera un elemento, actualiza una o varias de sus propiedades e intenta guardar los cambios, la operación de almacenamiento solamente se lleva a cabo si el número de versión del lado del cliente coincide con el número de versión del lado del servidor.DynamoDBMapper
incrementa el número de versión automáticamente. -
delete
: el métododelete
toma un objeto como parámetro yDynamoDBMapper
lleva a cabo una comprobación de versión antes de eliminar el elemento. La comprobación de versión se puede deshabilitar si se especificaDynamoDBMapperConfig.SaveBehavior.CLOBBER
en la solicitud.La implementación interna del bloqueo optimista en
DynamoDBMapper
utiliza la compatibilidad con las acciones de actualización condicional y eliminación condicional que DynamoDB proporciona. -
transactionWrite
—-
Put
: para un elemento nuevo,DynamoDBMapper
asigna un número de versión inicial de 1. Si recupera un elemento, actualiza una o varias de sus propiedades e intenta guardar los cambios, la operación put solamente se lleva a cabo si el número de versión del lado del cliente coincide con el número de versión del lado del servidor.DynamoDBMapper
incrementa el número de versión automáticamente. -
Update
: para un elemento nuevo,DynamoDBMapper
asigna un número de versión inicial de 1. Si recupera un elemento, actualiza una o varias de sus propiedades e intenta guardar los cambios, la operación update solamente se lleva a cabo si el número de versión del lado del cliente coincide con el número de versión del lado del servidor.DynamoDBMapper
incrementa el número de versión automáticamente. -
Delete
:DynamoDBMapper
realiza una comprobación de versión antes de eliminar el elemento. La operación de eliminación solo se realiza correctamente si coincide el número de versión en el lado del cliente y en el lado del servidor. -
ConditionCheck
: la anotación@DynamoDBVersionAttribute
no es compatible conConditionCheck
. Se producirá una excepción SdkClientException cuando un elementoConditionCheck
se anote con@DynamoDBVersionAttribute
.
-
Deshabilitación del bloqueo positivo
Para deshabilitar el bloqueo optimista, puede cambiar el valor de enumeración DynamoDBMapperConfig.SaveBehavior
de UPDATE
a CLOBBER
. Para ello, puede crear una instancia de DynamoDBMapperConfig
que omita la comprobación de versión y usar esta instancia en todas las solicitudes. Para obtener información acerca de DynamoDBMapperConfig.SaveBehavior
y otros parámetros opcionales de DynamoDBMapper
, consulte Ajustes de configuración opcionales para DynamoDBMapper .
También puede establecer el comportamiento de bloqueo para una operación específica. Por ejemplo, en el siguiente fragmento de código Java se usa DynamoDBMapper
para guardar un elemento de catálogo. Se agrega el parámetro opcional DynamoDBMapperConfig.SaveBehavior
al método DynamoDBMapperConfig
para especificar save
.
nota
El método transactionWrite method no admite la configuración DynamoDBMapperConfig.SaveBehavior. No se admite la deshabilitación del bloqueo optimista para transactionWrite.
ejemplo
DynamoDBMapper mapper = new DynamoDBMapper(client); // Load a catalog item. CatalogItem item = mapper.load(CatalogItem.class, 101); item.setTitle("This is a new title for the item"); ... // Save the item. mapper.save(item, new DynamoDBMapperConfig( DynamoDBMapperConfig.SaveBehavior.CLOBBER));