问题描述:
现在有一个需求,数据库表中有一个值,我需要查询出来,修改这个值之后再存回数据库。
下一个请求来到,查询出刚刚的新值,修改之后保存。
循环往复。。。
假设是多线程请求,那么第一个请求来到,获取值,在修改保存到数据库之前。第二个请求也来获取值。这时两个请求拿到的是同一份值,然后第一个请求保存,接着第二个请求保存。这种情况下如果每个请求修改值的逻辑相同,第一个请求保存的值将会被第二个请求覆盖。
即上面两个请求只做了一件事。因为第一个请求已经把事情做了,按照我们的想法,第二个请求应该拿着第一件事的结果去做下一件事。但是第二个请求仍然做的第一件事。出现了我们预料之外的情况。
我根据Postgresql的事务
和锁
的机制对这种情况进行了解决。
首先,我们要理解锁的概念。第一个请求拿到值,修改保存之前绝对不能让别的请求也拿到这个值。也就是在某个请求拿到值时要对该数据进行加锁。修改保存之后将锁放开。
其次,为什么需要使用到事务,是因为锁是基于事务实现的,锁只能在事务中使用。事务提交或者回滚时,锁被自动释放。
上面简单介绍了一些理论,接下来实践一下。
查询语句:
--开启事务
begin;
--锁表,锁定表之后只有当前事务可以操作。具体锁表还是锁行视业务而定
LOCK TABLE count IN ACCESS EXCLUSIVE MODE;
--查询
select * from disorder_count limit 1 ;
修改语句:
--更新数据
update count set count = ?1 ;
--提交事务
commit ;
执行完查询语句之后,直到当前事务出现commit
获取rollback
,锁才会释放,当前事务才会停止。
若心存疑惑,可自行研究postgresql
的事务
和锁
相关内容。