PolarDB-X 1.0柔性事务的典型场景包括“跨库转账”,“用户注册”和“商品优惠”。在这些场景里,柔性事务能够很好的保证事务原子性,并且提供良好的性能。
跨库转账
典型的跨库事务场景是从账户 A向账户B转账。
SET autocommit = 0;
SET drds_transaction_policy = 'flexible';
SELECT balance FROM account WHERE id = 'A'; -- 分库 1
UPDATE account SET balance = balance - 100 WHERE id = 'A'; -- 分库 1
UPDATE account SET balance = balance + 100 WHERE id = 'B'; -- 分库 2
COMMIT;
PolarDB-X 1.0支持balance = balance - 100
操作的完美回滚,能够自动生成对应的反向转账语句:
UPDATE account SET balance = balance + 100 WHERE id = 'A'
因此即使“分库2”事务提交失败,A的账户金额也可以正确回滚到转账前的状态。
优化点: 在这个场景下,由于转账给B的步骤不影响业务成功,因此可以用后置执行方式优化:
/*TDDL:DEFER*/ UPDATE account SET balance = balance + 100 WHERE id = 'B'
这样,只要账户A扣款成功,事务就可以提前结束。PolarDB-X 1.0将保证账户B的转入最终一致地完成。
用户注册
用户注册场景通常需要校验用户的登录名、手机号唯一。因此,通常应用需要在login_info表校验登录名的唯一性,再写入user信息。
SET autocommit = 0;
SET drds_transaction_policy = 'flexible';
SELECT user_id FROM login_info WHERE login_id = 'jenny'; -- 分库 1
INSERT INTO login_info (login_id, user_id) VALUES ('jenny', 321); -- 分库 1
INSERT INTO user (id, login_id, name) VALUES (321, 'jenny', 'Jenny Den'); -- 分库 2
COMMIT;
PolarDB-X 1.0柔性事务可以保证如果login_id或者ID全局不唯一时,事务完全回滚。如果事务提交失败,写入的login_info信息将在补偿回滚时被彻底删除。
商品优惠
商品优惠场景在库存不足或者用户优惠券已使用的情况下都需要返回失败。
SET autocommit = 0;
SET drds_transaction_policy = 'flexible';
SELECT stock FROM inventory WHERE id = 123; -- 分库 1
UPDATE inventory SET stock = stock - 1 WHERE id = 123 AND stock > 0; -- 分库 1
SELECT id FROM coupon WHERE used = 0; -- 分库 2
UPDATE coupon SET used = 1 WHERE id = 789 AND used = 0; -- 分库 1
COMMIT;
应用在stock > 0
或者used = 0
条件不满足时可以用ROLLBACK
正常回滚。在异常情况下,PolarDB-X 1.0将执行如下回滚语句,实现inventory与coupon数据的正确回滚。
回滚库存数据:
UPDATE inventory SET stock = stock + 1 WHERE id = 123
回滚优惠券使用:
UPDATE coupon SET used = 0 WHERE id = 789