为数据表开启局部事务后,使用局部事务功能,您可以创建数据范围在一个分区键值内的局部事务并对局部事务中的数据进行读写操作。通过使用局部事务您可以实现单行或多行读写的原子操作。
使用局部事务可以指定某个分区键值内的操作是原子的,对分区键值内的数据进行的操作要么全部成功要么全部失败,并且所提供的隔离级别为读已提交。
前提条件
已初始化Client,详情请参见初始化OTSClient。
使用方法
使用startLocalTransaction在指定的分区键值创建一个局部事务,并获取局部事务ID。
对局部事务范围内的数据进行读写操作。
支持对局部事务进行操作的接口为GetRow、PutRow、DeleteRow、UpdateRow、BatchWriteRow和GetRange。
使用commitTransaction提交局部事务或者使用abortTransaction丢弃局部事务。
注意事项
主键自增列功能和局部事务功能不能同时使用。
局部事务通过悲观锁(Pessimistic Lock)实现并发控制。
每个局部事务从创建开始生命周期最长为60秒。
如果超过60秒未提交局部事务或丢弃局部事务,则表格存储服务端会认为此局部事务超时,并将局部事务丢弃。
如果创建局部事务时超时,则请求可能在表格存储服务端已执行成功,此时请等待该局部事务超时后重新创建。
未提交的局部事务可能会失效,如果出现此情况,则需要重试该局部事务内的操作。
如果未对局部事务范围内的数据进行写操作,则提交局部事务或丢弃局部事务的操作是等同的。
在局部事务中读写数据有如下限制:
不能使用局部事务ID访问局部事务范围(即创建时使用的分区键值)以外的数据。
同一个局部事务中所有写请求的分区键值必须与创建局部事务时的分区键值相同,读请求则无此限制。
一个局部事务同时只能用于一个请求中,在使用局部事务期间,其他使用此局部事务ID的操作均会失败。
每个局部事务中两次读写操作的最大间隔为60秒。
如果超过60秒未操作局部事务,则表格存储服务端会认为此局部事务超时,并将局部事务丢弃。
每个局部事务中写入的数据量最大为4 MB,按正常的写请求数据量计算规则累加。
如果在局部事务中写入了未指定版本号的Cell,则该Cell的版本号会在写入数据时(而非提交局部事务时)由表格存储服务端自动生成,生成规则与正常写入一个未指定版本号的Cell相同。
如果BatchWriteRow请求中带有局部事务ID,则此请求中所有行只能操作该局部事务ID对应的表。
在使用局部事务期间,对应分区键值的数据会被加上写锁,只有持有局部事务ID在局部事务范围内的写请求才会成功。其他非事务请求或持有其他局部事务ID在局部事务范围内的写请求均会失败。在局部事务提交、丢弃或超时后,对应的锁也会被释放。
带有局部事务ID的读写请求失败不会影响局部事务本身的存活情况,您可以指定重试规则进行重试或者主动丢弃当前局部事务。
接口
局部事务相关的startLocalTransaction、commitTransaction和abortTransaction的接口信息如下。
startLocalTransaction
/**
* 创建局部事务,获取局部事务ID。
* @api
* @param [] $request
* 请求参数:数据表名称、分区键。
* @return [] 请求返回。
* @throws OTSClientException 当参数检查出错或服务端返回校验出错时抛出异常。
* @throws OTSServerException 当OTS服务端返回错误时抛出异常。
* @example "src/examples/StartLocalTransaction.php" 50
*/
public function startLocalTransaction(array $request)
commitTransaction
/**
* 提交局部事务。
* @api
*
* @param [] $request
* 请求参数:局部事务ID。
* @return [] 请求返回。
* @throws OTSClientException 当参数检查出错或服务端返回校验出错时抛出异常。
* @throws OTSServerException 当OTS服务端返回错误时抛出异常。
* @example "src/examples/CommitTransaction.php" 50
*/
public function commitTransaction(array $request)
abortTransaction
/**
* 丢弃局部事务。
* @api
*
* @param [] $request
* 请求参数:局部事务ID。
* @return [] 请求返回。
* @throws OTSClientException 当参数检查出错或服务端返回校验出错时。
* @throws OTSServerException 当OTS服务端返回错误时。
* @example "src/examples/AbortTransaction.php" 20
*/
public function abortTransaction(array $request)
参数
参数 | 说明 |
table_name | 数据表名称。 |
key | 数据表分区键。 创建局部事务时,只需要指定局部事务对应的分区键值。 |
primary_key | 数据表主键。 创建局部事务后,对局部事务范围内的数据进行读写操作时,需要指定完整主键。 |
transaction_id | 局部事务ID,用于唯一标识一个局部事务。 创建局部事务后,操作局部事务时均需要带上局部事务ID。 |
示例
使用局部事务写入一行数据
以下示例用于为表的指定分区键创建一个局部事务后,在局部事务内写入一行数据并提交事务。
// 获取局部事务ID。
$response = $client->startLocalTransaction (array (
'table_name' => 'TransactionTable',
// 主键为[PK0:INTEGER,PK1:STRING]。
'key' => array(
array('PK0', 123)
)
));
$attr = array();
$attr[] = ['col0', 'bbb'];
$request = [
'table_name' => 'TransactionTable',
'condition' => RowExistenceExpectationConst::CONST_IGNORE, //condition可以为IGNORE、EXPECT_EXIST和EXPECT_NOT_EXIST。
// 设置主键。
'primary_key' => [
['PK0', 123],
['PK1', 'abc']
],
'attribute_columns' => $attr,
'transaction_id' => $response['transaction_id']
];
// 执行putRow方法写入数据。
$client->putRow($request);
// 提交事务,使局部事务中的所有数据修改生效。您也可以通过丢弃事务来使数据写入不生效。
$client->commitTransaction(array(
'transaction_id' => $response['transaction_id']
));
// 丢弃事务,局部事务中的所有数据修改均不会应用到原有数据。
// $client->abortTransaction(array(
// 'transaction_id' => $response['transaction_id']
// ));
使用局部事务读取一行数据
以下示例用于为表的指定分区键创建一个局部事务后,在局部事务内读取一行数据。
// 获取局部事务ID。
$response = $client->startLocalTransaction (array (
'table_name' => 'TransactionTable',
// 主键为[PK0:INTEGER,PK1:STRING]。
'key' => array(
array('PK0', 123)
)
));
$request = array(
'table_name' => 'TransactionTable',
// 设置主键。
'primary_key' => array (
array('PK0', 123),
array('PK1', 'abc')
),
'max_versions' => 1,
'columns_to_get' => ['col0'],
'transaction_id' => $response['transaction_id']
);
// 执行getRow方法读取数据。
$client->getRow($request);
// 提交或丢弃局部事务。对于读操作来说,提交局部事务或丢弃局部事务的操作是等同的。
// 提交局部事务,使局部事务中的所有数据修改生效。
$client->commitTransaction(array(//提交事务
'transaction_id' => $response['transaction_id']
));
// 丢弃局部事务,局部事务中的所有数据修改均不会应用到原有数据。
// $client->abortTransaction(array(
// 'transaction_id' => $response['transaction_id']
// ));
相关文档
如果要在局部事务内进行批量写入、范围读取等操作,请在创建局部事务后,使用写入数据或者读取数据文档中的相应操作示例以及在请求中带上局部事务ID实现。