数据库事务优化-乐观锁

  最近优化一个接口的性能,发现是为了保证数据一致性,需要依赖数据库事务。所以MySQL成为了性能的瓶颈。

业务需求:

扣除用户的积分,兑换库存礼品。

1、礼品不能超发。

2、如礼品发放成功,必须成功扣减用户的积分,保证经济利益不受损害。

3、用户礼品对换有次数限制。


代码示例:

@启动事务

foo1(){

查询礼品信息和数量()

判断礼品是否存在,return

查询用户的积分()

判断用户积分是否够兑换礼品,return

foo2(礼品价值,兑换数量)

}


foo2(礼品价值,兑换数量) {

统计用户礼品兑换次数()

判断兑换数量,return

用户积分更新(礼品价值*兑换数量)

礼品数量更新(兑换数量)

}

  从代码中看,foo1被包含在整个数据库事务中。一个方法执行,所以的SQL查询都被阻塞。

  在这5条SQL中,foo2中的两次更新操作必须在一起执行。foo1中的查询SQL可以不包含在数据库事务中。查询结果,作为更新时的判断条件,就可以保证查询的数据在更新之前没有被别人操作过。统计语句的结果,需要在程序中进行逻辑判断。在更新时,无法对统计结果是否改变进行有效的判断,除非再次统计数据。

  通过上面的分析对代码进行了适当的改造:

foo1(){

查询礼品信息和数量()

判断礼品是否存在,return

查询用户的积分()

判断用户积分是否够兑换礼品,return

foo2(礼品价值,兑换数量,用户当前积分)

}

@启动事务

foo2(礼品价值,兑换数量,用户当前积分) {

统计用户礼品兑换次数()

判断兑换数量,return

用户积分更新(礼品价值*兑换数量,用户当前积分)

礼品数量更新(兑换数量)

}

1、礼品数量更新,并没有判断是否与之前的数量相等,因为只要不超发就可以。

2、当用户进行积分更新时,where条件要判断当前的积分和之前查询出的积分是否一致。这里其实对业务逻辑增加了一些限制。既用户在进行积分兑换时,不能执行其它的操作。这个逻辑限制本身也符合真实业务场景,对用户操作体验没有影响。

  大家会发现瑞很多技术问题在网上都有现成的答案,并且是很多年以前的答案。但是在程序中还会犯一样的错误,也许是我们老了,新一代的程序员在成长过程还需要不断的重新摸索。

你可能感兴趣的:(数据库事务优化-乐观锁)