免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4585 | 回复: 9
打印 上一主题 下一主题

pg 不能存储过程当中锁某一行? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-04-20 22:48 |只看该作者 |倒序浏览
使用PGsql,就是冲着它跟oracle一样可以进行行锁定去的,结果在写存储过程的时候告诉我不能在存储过程当中使用for update/share.....这这这..存储过程内不能使用事务也就算了,基本代码写好点也能过去,但不能锁行这个就太说不过去了吧.难道是我没找到方法.....

论坛徽章:
0
2 [报告]
发表于 2009-04-20 23:58 |只看该作者
总算被我找到了方法...可以在function里面使用了.....虽然不是特别好用,而且需要注意的特别多.

论坛徽章:
0
3 [报告]
发表于 2009-04-21 21:26 |只看该作者

回复 #1 udbjqr 的帖子

官方的说法是:
FOR UPDATE causes the rows retrieved by the SELECT statement to be locked as though for update. This prevents them from being modified or deleted by other transactions until the current transaction ends. That is, other transactions that attempt UPDATE, DELETE, or SELECT FOR UPDATE of these rows will be blocked until the current transaction ends.

也就是说,只要在一个transaction中就可以用,不一定是function/procedure。

论坛徽章:
0
4 [报告]
发表于 2009-04-21 22:42 |只看该作者
这一行说的没错,也就是说如果你使用
begin;
  select * from table1 where id = 1 for update;
  ......
commit;

这样的写法,在这个事务当中这一行是被锁定的.直至事务结束.

但还有一段是告诉我,不能在一个plpgsql的funtion里面使用for update/share.这样的方法去锁一个行.我要的是在存储过程里面执行这样的锁行动作.前面的代码是可以执行的,但不能放在function ()里面.这样的限制好奇怪.我不放在存储过程里面我要锁单行的动作有什么意义.一般也没有谁写大段的sql代码而不用存储过程的吧.

倒是在网上找到一个解决方案,是使用 pg_advisory_lock来锁单行.但这个锁好奇怪,不是sql的标准锁.没有底的东西,不太敢用.....
再有就是直接在事务开始的时候更新行...这个方案还是我一个同事想出来的.想想也对,我直接update这一行,他存储过程总应该就锁住了吧.反正一个存储过程也不让我写commit或rollback savepoint 这样的东西..直接执行到最后,好在pgsql如果执行出错会回滚整个存储过程,不象sqlserver,在哪一行出错这一行不执行..前面的就不管了.....

论坛徽章:
0
5 [报告]
发表于 2009-04-22 08:44 |只看该作者
但还有一段是告诉我,不能在一个plpgsql的funtion里面使用for update/share.这样的方法去锁一个行.我要的是在存储过程里面执行这样的锁行动作.前面的代码是可以执行的,但不能放在function ()里面.这样的限制好奇怪.我不放在存储过程里面我要锁单行的动作有什么意义.一般也没有谁写大段的sql代码而不用存储过程的吧..


你从哪里看的? 你误解了

我从来没看到 有这限制

论坛徽章:
0
6 [报告]
发表于 2009-04-22 08:51 |只看该作者
好吧.我承认..的确我也没有在任何一个文档中看到,只在官网的邮件列表里面有看到说明,你把下面的代码拿出来执行一下你就知道了.看看异常提示哟
CREATE OR REPLACE FUNCTION f_getpasswd(len integer)
  RETURNS void AS
$BODY$
declare
begin
--就这一句了.
  select * from s_users where userid = 1 for update;

end;
$BODY$
  LANGUAGE 'plpgsql'

论坛徽章:
0
7 [报告]
发表于 2009-04-22 19:35 |只看该作者

回复 #6 udbjqr 的帖子

我测试运行正常,我的理解是在Function或Procedure中如果要用select的话要不就是在游标中使用,要不就是select...into。
如果只有一句select ename from emp where empno = 7521,在运行时会出现以下错误:
ERROR: query has no destination for result data
SQL 状态: 42601
指导建议:If you want to discard the results of a SELECT, use PERFORM instead.
上下文L/pgSQL function "f_getpasswd" line 5 at SQL statement


我在EDB PPAS 8.3(相当于PostgreSQL 8.3内核)中测试如下:

CREATE OR REPLACE FUNCTION f_getpasswd(len integer)
  RETURNS char AS
$BODY$
declare
  v_name emp.ename%TYPE;
begin
--就这一句了.
  select ename into v_name from emp where empno = 7521 for update;
  return v_name;
end;
$BODY$
LANGUAGE 'plpgsql'

select f_getpasswd(2);

论坛徽章:
0
8 [报告]
发表于 2009-04-23 14:40 |只看该作者
果然是可以,看样子果然还是在存储过程里面不能写单独的select语句..呵呵.十分感谢.

论坛徽章:
0
9 [报告]
发表于 2009-04-24 15:59 |只看该作者
You are welcome!

论坛徽章:
0
10 [报告]
发表于 2009-04-27 11:40 |只看该作者
我这里也使用正常啊.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP