PB多个客户端连接服务器数据库问题

时间:2022-09-23 17:09:15
小生用以下代码,将客户端连接到局域网的另一台机子上,打开一个客户端的时候,多能进行正常操作,打开二个,有一个是没有反应的,这是怎么回事。是那里的代码要改动,要怎么改呢,大侠帮忙一下。
// Profile ydf
SQLCA.DBMS = "OLE DB"
SQLCA.LogId = "sa"
SQLCA.AutoCommit = true
SQLCA.DBParm = "PROVIDER='SQLOLEDB',DATASOURCE='192.168.31.163',PROVIDERSTRING='database=BYD2015'"
connect using sqlca;

7 个解决方案

#1


引用 楼主 qq_29841149 的回复:
小生用以下代码,将客户端连接到局域网的另一台机子上,打开一个客户端的时候,多能进行正常操作,打开二个,有一个是没有反应的,这是怎么回事。是那里的代码要改动,要怎么改呢,大侠帮忙一下。
// Profile ydf
SQLCA.DBMS = "OLE DB"
SQLCA.LogId = "sa"
SQLCA.AutoCommit = true
SQLCA.DBParm = "PROVIDER='SQLOLEDB',DATASOURCE='192.168.31.163',PROVIDERSTRING='database=BYD2015'"
connect using sqlca;

这是连接数据库的,连接几个应该都没有问题,主要是看数据库设置的最大连接数,你的问题估计不是出在这里,是出在其它代码了

#2


sqlca.lock='RC'

#3


这个问题在SQL SERVER里头叫阻塞,并不是真正的死锁。
原因是由于多方面因素引起的:
1、最主要的原因是SQL SERVER 默认使用的是read commit, 而普通程序使用的加锁级别都是read uncommit. 使用read uncommit(也就是脏读)会影响数据的一致性,但并不是所有的处理都需要加锁。由于你的程序比较旧,所以我考虑没有对需要加锁的事务仔细分析,导致每读数据都要加锁,这个锁会和其他SELECT锁,和UPDATE的更新锁冲突,导致程序彼此等待,尤其是PB的DW,要么不使用事务,要么使用的事务比较长,那么如果有个伙计SELECT了数据不关闭他的DW,而这个DW又处于一个长事务中,其他的人只好等待等待,这样锁越加越多,就只好死机啦。
2、第二个原因与第一个原因类似,但是一般发生在类似代码表这样的表上,因为这类表被频繁访问,因此就形成了处理时候一个非常非常热的点。由于一所说的SELECT锁在这里很容易发生,因此更容易造成阻塞。另外,对于比较小的热点表,SQL SERVER处于性能考虑的原因,在频繁访问的情况下,会自动将行锁升级为表锁。一旦升级为表锁,那么其他访问表的进程就只好死翘翘了。

处理的方法很简单:
 1、并不是所有的地方都需要使用read commit的加锁级别,你从application中设置一句sqlca.lock="RU", 使用脏读,这样就可以去掉大多数不必要的SELECT行锁。然后在一定要读最新数据的地方,把SQLCA。LOCK改为RC,用完后再改回来。
这样就避免了几乎80%的阻塞。
2、对于由于行更新,或者其他UPDATE导致的锁,一般数据库会自己协调,在事务比较长的情况下,这需要你对原来的程序做适当的修改。把长事务变为几个小的事务,在事务中做更新操作,不要插入用户的交互。这是系统的设计原则。
如果你的系统对事务的要求不严格,又不想改动原来的程序,办法更简单,在前面
SQLCA。LOCK的基础上,加句SQLCA。AUTOCOMMIT=TRUE,这样每数据修改自动提交,就可以避免大多数由于更新产生的死锁和阻塞。
3、最后要对付的是刚才说的被大量应用频繁访问的表(HOT TABLE),如果你的系统允许使用RU加锁级别,那么不用太考虑,因为SELECT已经不会导致锁定了。
但是如果你不能使用RU方式(1里头提到的办法),
那么要采用这样的手段:
使用索引把更新锁,SELECT锁来分开,同时也避免SQLSERVER傻傻为了性能的原因把行锁升级为表锁。
具体办法是建立一个索引,如果可以的话使用聚集索引,因为聚集索引采用的是类似HASH的检索方式,这样当查找索引的时候,就不需要访问数据表了。
另一种办法,是将你SELECT语句中要检索的数据都加到索引中,例如你检索NAME,SEX,AGE,如果你把三个数据都加入了索引,这就意味着SELECT语句只要找到索引,就已经找到了最后要选取的数据(从索引中),这样自然不会去LOCK表了。这样做的时候要针对你的程序仔细选择索引,否则把索引变成了表的一个备份就没有意义了。

总结一下,就三招:
1、降低加锁级别,2、可能的话使用自动提交 3、采用措施避免表访问的热点
当然,必要的时候优化你的应用程序,仔细划分事务也是很重要的。

#4



关于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用MSS连接时的默认级别,适用于大多数情况,当然还要看你的具体应用了

#5


引用 4 楼 lzp_lrp 的回复:
关于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用MSS连接时的默认级别,适用于大多数情况,当然还要看你的具体应用了


版主大拿,解释的非常清楚,收藏

#6


可能就是执行了语句未提交,导致加锁 

#7


你少了一个参数
sqlca.lock='RC' 

#1


引用 楼主 qq_29841149 的回复:
小生用以下代码,将客户端连接到局域网的另一台机子上,打开一个客户端的时候,多能进行正常操作,打开二个,有一个是没有反应的,这是怎么回事。是那里的代码要改动,要怎么改呢,大侠帮忙一下。
// Profile ydf
SQLCA.DBMS = "OLE DB"
SQLCA.LogId = "sa"
SQLCA.AutoCommit = true
SQLCA.DBParm = "PROVIDER='SQLOLEDB',DATASOURCE='192.168.31.163',PROVIDERSTRING='database=BYD2015'"
connect using sqlca;

这是连接数据库的,连接几个应该都没有问题,主要是看数据库设置的最大连接数,你的问题估计不是出在这里,是出在其它代码了

#2


sqlca.lock='RC'

#3


这个问题在SQL SERVER里头叫阻塞,并不是真正的死锁。
原因是由于多方面因素引起的:
1、最主要的原因是SQL SERVER 默认使用的是read commit, 而普通程序使用的加锁级别都是read uncommit. 使用read uncommit(也就是脏读)会影响数据的一致性,但并不是所有的处理都需要加锁。由于你的程序比较旧,所以我考虑没有对需要加锁的事务仔细分析,导致每读数据都要加锁,这个锁会和其他SELECT锁,和UPDATE的更新锁冲突,导致程序彼此等待,尤其是PB的DW,要么不使用事务,要么使用的事务比较长,那么如果有个伙计SELECT了数据不关闭他的DW,而这个DW又处于一个长事务中,其他的人只好等待等待,这样锁越加越多,就只好死机啦。
2、第二个原因与第一个原因类似,但是一般发生在类似代码表这样的表上,因为这类表被频繁访问,因此就形成了处理时候一个非常非常热的点。由于一所说的SELECT锁在这里很容易发生,因此更容易造成阻塞。另外,对于比较小的热点表,SQL SERVER处于性能考虑的原因,在频繁访问的情况下,会自动将行锁升级为表锁。一旦升级为表锁,那么其他访问表的进程就只好死翘翘了。

处理的方法很简单:
 1、并不是所有的地方都需要使用read commit的加锁级别,你从application中设置一句sqlca.lock="RU", 使用脏读,这样就可以去掉大多数不必要的SELECT行锁。然后在一定要读最新数据的地方,把SQLCA。LOCK改为RC,用完后再改回来。
这样就避免了几乎80%的阻塞。
2、对于由于行更新,或者其他UPDATE导致的锁,一般数据库会自己协调,在事务比较长的情况下,这需要你对原来的程序做适当的修改。把长事务变为几个小的事务,在事务中做更新操作,不要插入用户的交互。这是系统的设计原则。
如果你的系统对事务的要求不严格,又不想改动原来的程序,办法更简单,在前面
SQLCA。LOCK的基础上,加句SQLCA。AUTOCOMMIT=TRUE,这样每数据修改自动提交,就可以避免大多数由于更新产生的死锁和阻塞。
3、最后要对付的是刚才说的被大量应用频繁访问的表(HOT TABLE),如果你的系统允许使用RU加锁级别,那么不用太考虑,因为SELECT已经不会导致锁定了。
但是如果你不能使用RU方式(1里头提到的办法),
那么要采用这样的手段:
使用索引把更新锁,SELECT锁来分开,同时也避免SQLSERVER傻傻为了性能的原因把行锁升级为表锁。
具体办法是建立一个索引,如果可以的话使用聚集索引,因为聚集索引采用的是类似HASH的检索方式,这样当查找索引的时候,就不需要访问数据表了。
另一种办法,是将你SELECT语句中要检索的数据都加到索引中,例如你检索NAME,SEX,AGE,如果你把三个数据都加入了索引,这就意味着SELECT语句只要找到索引,就已经找到了最后要选取的数据(从索引中),这样自然不会去LOCK表了。这样做的时候要针对你的程序仔细选择索引,否则把索引变成了表的一个备份就没有意义了。

总结一下,就三招:
1、降低加锁级别,2、可能的话使用自动提交 3、采用措施避免表访问的热点
当然,必要的时候优化你的应用程序,仔细划分事务也是很重要的。

#4



关于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用MSS连接时的默认级别,适用于大多数情况,当然还要看你的具体应用了

#5


引用 4 楼 lzp_lrp 的回复:
关于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用MSS连接时的默认级别,适用于大多数情况,当然还要看你的具体应用了


版主大拿,解释的非常清楚,收藏

#6


可能就是执行了语句未提交,导致加锁 

#7


你少了一个参数
sqlca.lock='RC'