前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Postgresql select 语句 share VS update 用过吗?

Postgresql select 语句 share VS update 用过吗?

作者头像
AustinDatabases
发布2020-09-10 16:13:04
1.9K0
发布2020-09-10 16:13:04
举报
文章被收录于专栏:AustinDatabasesAustinDatabases

for

Postgresql select 语句不够用吗, select for share ,select for udpate 这样的语句我从来没有用过,是不是多余。

回答是:NO

曾经还听到一个声音,select = select for share 没差的,到底是不是这样

首先要确认一点的是,无论是 share 还是update 都是因为在业务中的逻辑造成你要访问的数据需要保护,所以如果你还没有用过,可能你的业务比较简单,或者你的业务并不简单,只是你没有考虑某些问题,而从未使用过他们。

假设我们下面的图中的一个业务,下面是一个拍卖二手车的场景,在各地的拍卖都在买同一个二手车,人们在竞价,而这时有时间限制的,所以每个人读到的最近一次的购买人出的价格,并在这个价格上,提价。而这里面就会牵扯一个问题,如果我要在价格上更改,那这时的价格被我独占,否则我无法在得到一个价格后,更改的时候保证这个价格不变,然后在这个价格上我在加钱。

上面的业务场景,就设计到下面的这段截图的操作

1 首先他必须是一个事务

2 在我查询的时候我必须不能让人在更改价格

3 我要迅速的更新这个价格

4 然后释放,让别人继续出价

想想如果没有for update 这个语句,那在程序上要花费多大的力气来满足这个“事务”。

for update 将这一行数据上了锁,一个别人都不能对这行数据更改的锁,事情就到此为止了,NO NO NO

如果这时候多个人都要加 for update 锁会怎么样,那一定只能有一个人,加上这个锁。

session 1

session 2

从上图我们可以很清晰的看出,session2 无法将select for update 语句执行,一直在等待,他等待session 1 释放那个锁。session 2 只能等到 session 1 commit 后才能获得那个锁,进行更改,而那时数据一个改变,他读取的数据必然是session 1 已经更改的数据,周而复始。

我们可以把上面的过程叫做,安全更新。

那这for update 产生了什么锁我们的看一下

可以很清晰的看到 for update 加了 exclusivelock 排他锁

那问题来了,如果很多人都在竞争这行数据,那应用程序那边怎么办,都在等待,如果这边设计有问题,并没有超时设计,那其他的应用不就都卡死了。

那我们就的拿出for update NOWAIT 这条语句

session 1

session 2

从上图可以很清楚的看到,使用了for update nowait 则马上因为已经对那行数据上锁了,所以其他session 在去锁,就会报错,并提示,无法获得lock。

巧妙的使用这两句话,可以减少很多在应用程序中需要考虑的事情,简简单单就将事情解决了。

那么问题还没有完,如果两个事物锁定的记录部分重合,部分不重合,那我应该怎么办,业务逻辑中,例如抢注商标,在你确认的一刻,你有两个选择,你选择的这一批商标里面,有一部分已经被抢注了,一部分有,你此时是要不都注册,要不就都不注册,实际上此时你希望还有第三种选择,就是那个商标没有注册,你就马上注册上,其他就随它去。

那这时事情怎么办?shiyong skip locked 就可以满足上面的需求。

所以一个 for update 的用法和对应的业务逻辑都不同,适当的选择不同的方法可以事半功倍。

那说了这么半天,for share 到底又有几个意思。

相对于 for update for share 用法比较单纯,一句话,有我你别改,但都可以读。

最后一定会有一个问题,for share 和 for update 之间的最大的区别在哪里,下边这张图给出的答案。

附:上面使用的查询锁的view 代码

CREATE VIEW lockview AS

SELECT pid, virtualtransaction AS vxid, locktype AS lock_type,

mode AS lock_mode, granted,

CASE

WHEN virtualxid IS NOT NULL AND transactionid IS NOT NULL

THEN virtualxid || ' ' || transactionid

WHEN virtualxid::text IS NOT NULL

THEN virtualxid

ELSE transactionid::text END AS xid_lock, relname,

page, tuple, classid, objid, objsubid

FROM pg_locks LEFT OUTER JOIN pg_class ON (pg_locks.relation = pg_class.oid)

WHERE -- do not show our view’s locks

pid != pg_backend_pid();

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-09-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AustinDatabases 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档