我遇到了这样的错误,我尝试 baidu/google,但是没有解决方法.
V 友们,我应该如何解决他?
1
suke119 2023-01-18 18:26:59 +08:00 via iPhone
。。。。常见的乐观锁不就搞定了
|
2
seers 2023-01-18 18:35:17 +08:00
分布式锁
|
3
yaodao 2023-01-18 19:41:07 +08:00 via iPhone
如果并发量不大,可以用简单的 redis 分布式锁或者数据库的乐观锁
|
4
lsrnb OP @suke119 乐观锁是修改 version 吗?第一次修改是 0,第二次修改是 1 这样吗?
update `user` set stau = 100001, version = 1 where stau = 100000 and version = 0; 这样的我测试了不行,因为第一台服务器修改的结果还没传到数据库 version 还是=0,第二台服务器执行还是返回跟第一台相同的结果 |
5
suke119 2023-01-18 21:23:31 +08:00 via iPhone
@lsrnb 所以问题出在你的理解上啊,任何客户端都可以修改,你无法控制客户端的行为,你能做的只有保证谁入库谁为主,如果第一个因为网络有问题没有修改完成,但是此时第二个用户可以任何操作的,他有这个权利,如果他的行为 db 提交,不管是不是在上一个用户之前都是正确✅的,完成后第一个用户提交自然就因为版本不对失败
|
6
h0099 2023-01-19 00:30:49 +08:00
乐观并发控制是要求每个客户端的后续读写都得依赖于此前查询所获得的的`ROW_VERSION`
比如事务 1`SELECT yi, ver FROM t`获得`(a,0)` 那么事务 1 后续的所有对该行的读写( SELECT/UPDATE )都得依赖于`ver=0`这个此前获得的事实 也就是对于读:事务 1 期望重新`SELECT yi, ver FROM t`获得的还是`(a,0)`,这叫做`REPEATABLE READ`(避免了幻读`phantom read`),注意 mysql 默认的事务隔离级别就是`REPEATABLE READ`所以默认是已经保证了在同一事务内不断重新执行`SELECT yi, ver FROM t`返回的永远都是`(a,0)` 对于写:事务 1 期望`UPDATE t SET 某个其他字段 = 某值 WHERE yi = a AND ver = 0`所返回的`affected rows`是 1 行,而如果不是 1 行而是 0 行就意味着表 t 中已经不存在符合约束`WHERE yi = a AND ver = 0`的行,也就是说行`yi=a`已经被其他事务修改了 建议参考以某企业级 orm EFCore 为背景的 MSDN 微软谜语: https://learn.microsoft.com/en-us/ef/core/saving/concurrency 以及我之前对于类似的场景(但是是 INSERT-only 而不是 UPDATE )使用了数据库层提供的悲观并发控制,毕竟在 SQL 末尾加`FOR UPDATE`可比在 mysql 里用 TRIGGER 模拟单调递增的自增 sql server 的 ROW_VERSION 类型然后在程序业务逻辑里写乐观控制所带来的一大堆 if 简单多了: https://www.v2ex.com/t/908047 |
7
dog82 2023-01-19 08:39:47 +08:00
认识到这个问题所在并能想办法解决,就晋级成中级码农了
|
8
Freeego 2023-01-19 10:57:58 +08:00
这个需求有点奇怪,意思是前端只处理一次数据?这样的话在后端加个分布式锁,在查询命令的时候加锁,字段 yi 修改到 1 之后再解锁。
|
9
matepi 2023-01-19 14:48:56 +08:00
除了前面各位讲到的锁方式
其实在非强联机场景下可以用任务队列的方式,也会有很多的好处 |