一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第12天,点击查看活动详情。 导致产生事务的根源就是分库分表。
Update 操作的幂等性分为两个部分。第一部分是有唯一业务号去更新数据的情况,另外一种是没有唯一业务号去更新数据的情况。这种情况我们会在后面给大家做介绍,就是使用这个token的方式统一的去解决操作的密等性。
针对有唯一业务号这种情况,我们就要根据这个唯一的业务号去更新这一条数据。我们怎么去更新呢?一般的情况下。都是先查出要修改的这条数据,然后把这个要修改的数据返回到页面当中,将这个数据的版本号放在隐藏域。
这里边有一个关键词就是数据的版本号。修改操作一般在系统里怎么做啊?是不是一开始都要进入一个列表页?比如用户列表页,包括订单列表页,它都是先有一个列表页,然后我们在列表页当中每一条记录的后边有一个修改按钮,然后跳到具体的修改页面,比如要修改其中的某一个用户,或修改其中的某一个订单,这个时候用户 id 和订单 id 是不是就是它的唯一业务号?因为我们跳到详情页,要根据这个用户 id 或者订单 id 把相应的这一条数据给查询出来。那么这个用户 id 和订单 id 就是唯一的业务号,我们在这个详情页把这个信息修改完成以后,我们要根据这个唯一的业务号去更新数据。那么这个时候我们更新的这一条数据是不是就是一条唯一的数据。
那么这个数据版本号是什么意思呢?因为我们这个时候在更新的时候要去使用 update 的乐观锁。一提到乐观锁,那么肯定要联想到数据的版本,那么这个时候数据的版本号就起到了非常重要的作用。这个数据版本号我们可以用数据的更新时间作为它的数据版本号也是没有问题的。
然后用户修改数据,修改完了以后点击提交,把这个版本号也一同提交到后台。
然后在更新这条数据的时候,要使用这个版本号作为更新条件。更新的时候就使用类似于下面的这条一句。
update set version=version+1,xxx=${xxx} where id = xxx and version = ${version}
根据上面这条语句更新的时候,更新的数据就不会出现错误了,你不会把别人已经修改过的数据,你再进行更新,这是不是就有问题了?
这个 Update 操作具体 SQL 语句。比如现在修改一条数据,一开始这个用户的用户名叫做“张三”,现在给它修改成为“李四”,然后这个时候点击提交按钮,发送了第一条这个 update 一句。
然后这个时候更新的响应还没有回来,紧跟着我又点击了一次提交。这个时候是不是先后我发送了两条更新的请求啊?那么第一条打不开的语句更新完以后,它的用户名变成了“李四”,那么第二条语句再去执行更新,是不是又变成“李四”?
根据前面幂等性的定义,发现如果是这种情况下的话,你发出了两条更新语句,你最后的执行结果是一样的,并没有产生额外的影响。像这种情况下,update 语句也是一个幂等性的操作。
那么什么时候这个 update 的语句变成了不是幂等性呢?比如用户表里边儿还有另外一个字段,它记录着用户的修改次数。同样还是进入到修改用户的这个页面,我点击第一次提交,它标志着我修改了一次。这个时候我的修改次数呢应该加 1,但是页面没有给出响应,我又连着点击了多次这个提交按钮。修改次数它到底要不要增加多次呢,还是说只增加 1 次呢?当然是只增加一次了。因为按照我用户的意图,其实只是修改了它一次。虽然我点击了多次的提交,但是你不应该把这个修改次数增加多次。这个时候,这个接口不具备幂等性。那么这个时候就要使用这种update 语句的方式,保证接口是幂等性,让它多次操作后,修改次数还是只增加一次。
这个就是使用乐观锁,然后还有一个 update 的与生俱来的行锁去保证接口的幂等性。
最后没有业务号,就使用 Token 机制。