最近使用 PB12+SQLSERVER 2005 开发程序,发现一个问题:后台有一触发器,触发功能是insert一个
表,update另一个表。当使用OLE、SNC接口时会出现并发错误 :[/size]
Row changed between retrieve and update.
No changes made to database.
UPDATE j_cust_ps_in2 SET gz_ok = 'N' WHERE numc_no = '0000000066' AND m_getrow = '00001'
屏蔽掉触发器中部分语句测试,发现只要是 执行其中的任何两条或以上语句 并发就会出现,无论这两条
语句是否操作同一个表。而执行一条语句时 并发消失。
更为奇怪的是,当在触发器里加入 select ''语句时 并发也会消失。实在不解。
但当使用ADO接口时 没有并发问题。
以下是错误DEMO源码。
http://download.csdn.net/detail/hmh3393253/7972021
进入程序后 请审核或者反审核单据时就能看到此错误。里面代码很少,比较容易分析。
这个错误困扰了很久。请大家下载帮忙分析分析原因,万分感谢。
[size=13px]
------解决思路----------------------
试试在连接数据库的地方增加
sqlca.lock='RU' 或者 sqlca.lock='RC'
------解决思路----------------------
可以参考以下文章
pb11-pb12查询死锁问题解决方法一、 原先PB11中连接方式是:
// Profile iadserver
SQLCA.DBMS = "OLE DB"
SQLCA.LogPass =profilestring('dbms.ini' , "database" , "logpass" , "")
SQLCA.LogId = profilestring('dbms.ini', "database" , "logid" , "")
SQLCA.AutoCommit = False
SQLCA.DBParm = "PROVIDER='SQLOLEDB',"+&
"DATASOURCE='" + profilestring('dbms.ini' , "database" , "serverip" , "") + "'," +&
"PROVIDERSTRING='Database="+profilestring('dbms.ini' , "database" , "dbname" , "")+"'"
connect using sqlca ;
if SQLCA.SQLCode <> 0 then
messagebox("提示信息:", '连接数据库出错!' + SQLCA.SQLErrText , stopsign!)
rollback using sqlca ;
halt close
end if
二、经高人指点后的连接方式
用以上连接方式,经常在查询的时候都死锁,没有办法,在查询完成后都要COMMIT,后来有位高人指点,增加了
加上sqlca.lock='RU' 或者 sqlca.lock='RC' 可以解决死锁问题。
具体连接方式如下:
// Profile iadserver
SQLCA.DBMS = "OLE DB"
SQLCA.LogPass =profilestring('dbms.ini' , "database" , "logpass" , "")
SQLCA.LogId = profilestring('dbms.ini', "database" , "logid" , "")
SQLCA.AutoCommit = False
SQLCA.Lock='RC'
SQLCA.DBParm = "PROVIDER='SQLOLEDB',"+&
"DATASOURCE='" + profilestring('dbms.ini' , "database" , "serverip" , "") + "'," +&
"PROVIDERSTRING='Database="+profilestring('dbms.ini' , "database" , "dbname" , "")+"'"
connect using sqlca ;
if SQLCA.SQLCode <> 0 then
messagebox("提示信息:", '连接数据库出错!' + SQLCA.SQLErrText , stopsign!)
rollback using sqlca ;
halt close
end if
三、 MS SQL中lock属性
RU Read Uncommitted
RC Read Committed
RR Repeatable Read
TS Serializable
查阅SQL SERVER2005联机丛书有以下描述:
sql server 数据库引擎隔离级别
SQL-99 标准定义了下列隔离级别,Microsoft SQL Server Database Engine 支持所有这些隔离级别:
未提交读(隔离事务的最低级别,只能保证不读取物理上损坏的数据)
已提交读(数据库引擎 的默认级别)
可重复读
可序列化(隔离事务的最高级别,事务之间完全隔离)
实际测试发现,当设置sqlca.lock='RR'可重复读时,会出现死锁,其他三种不会。
似乎PB10以上版本缺省是sqlca.lock='RR'才会造成死锁,一般是用“RC”。
低版本的PB用MS SQLSERVER连接时的默认级别,适用于大多数情况,当然还要看你的具体应用了
------解决思路----------------------
哈哈,我也遇到过这种情况,很简单,在trigger 语句的开始位置加入以下语句:set nocount on,应该就解决你的问题。
------解决思路----------------------
那个开关是返回行为0时不会报错的开头,和你的触发器是否执行没有关系,你的触发发器应该是执行了,但行数为0,具体的原因还是查一下对应的sql是否有误
------解决思路----------------------
哈哈,我也遇到过这种情况,很简单,在trigger 语句的开始位置加入以下语句:set nocount on,应该就解决你的问题。
这样是否有其他的问题产生?
我从pb9升级到pb11后就发现很多trigger都有楼主讲这个现象,后来所有trigger都加上set nocount on就没问题了,估计禁止SQL Server内部统计,这个只是在调试的时候用到,加上去还可以加快速度,你放心加上去吧,我加了后一切都正常,没发现什么特别情况,一般的sp,trigger都是建议加这条语句上去,减少不要的内部统计
------解决思路----------------------
这个问题你解决了么?
------解决思路----------------------
哈哈,我也遇到过这种情况,很简单,在trigger 语句的开始位置加入以下语句:set nocount on,应该就解决你的问题。
我也是这样解决的
你试过这种方法了吗?