1
xipushi 2018-12-17 22:32:05 +08:00 via iPhone 1
如果程序部署多个,程序锁不搞事的。
一个写库的话,直接 update。update set count=count-1 where count>1,影响行数大于 1,说明成功。 Zookeeper,redis |
3
liunull 2018-12-17 22:39:44 +08:00 via Android 1
我们公司是给账户记录加版本号,类似 CAS,冲突就重试,一般单个用户并发修改数据库的概率很小
|
6
Sharuru 2018-12-17 22:45:26 +08:00 via Android
乐观锁呀,带 version 字段就完事儿了。
|
7
yidinghe 2018-12-17 22:50:31 +08:00 via Android 1
假设用户积分为 8,现在要扣掉 5 分,那么 SQL 语句为:
update user set score=score-5 where userid=xxx and score=8 and score>=5 这个语句的作用是在数据库操作层面保证:1、这个扣 5 分的操作只会执行一次; 2、并发的扣分操作只会有一个执行成功; 3、任何成功的扣分操作都不会导致用户积分变成负数。 |
9
lhx2008 OP |
11
xipushi 2018-12-17 23:38:53 +08:00 1
@lhx2008 我觉得 score=8 就可以了。
hibernate 的 version 貌似跟 update 语句效果一样,还可以少写几个 SQL。hibernate 默认 session 的生命周期比较反人类。 |
12
xipushi 2018-12-17 23:42:38 +08:00 1
纠正上条,是 JPA 的 session.
|
13
liunull 2018-12-18 00:01:07 +08:00 via Android
@lhx2008 看来我表达能不不行😂,其实就是 6 楼说的这个,数据库里,账户表加 version 字段
|
14
lcorange 2018-12-18 00:19:11 +08:00
MySQL 的 select for update 语法能满足要求么
|
16
sagaxu 2018-12-18 01:08:23 +08:00 via Android
@lhx2008 只要用 innodb,你直接写 update where version=xxx 一样可能产生行锁,MySQL 会检测死锁。select for update 反而是避免死锁的办法。
To avoid deadlocks when performing multiple concurrent write operations on a single InnoDB table, acquire necessary locks at the start of the transaction by issuing a SELECT ... FOR UPDATE statement for each group of rows expected to be modified, even if the data change statements come later in the transaction. https://dev.mysql.com/doc/refman/8.0/en/internal-locking.html |