求教数据库并发控制的解决方案,欢迎讨论

guxing 2004-07-30 04:43:52
本人最近做了一个系统,对时间和准确性要求很高
我开发一个系统其中有复杂的计算,放在SQL的存储过程中,
每次调用要花0.1-0.4s 时间不等
同时可能有15台电脑同时操作上述调用

在经过强度测试时,发现会出现错误
1,种是调用存储过程未返回错误,但数据丢失,未入库(莫名其妙)
2,另一种是调用存储过程出错,一般会2台及以上机器同时出错,但并
没有锁表,也找不到原因

在存储过程有单独事务,局部临时表
由于业务原因,其中有多表的更新

现在仅对不会脏读的SELECT 加了 with (nolock)
其它是系统默认的锁

请问
我要怎样改进才能解决上述的问题
非常感谢您 的帮助
...全文
340 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
guxing 2004-08-01
  • 打赏
  • 举报
回复
现在已经大概找到原因了。
好象是死锁
返回错误
1205
事务(进程 ID %1!)与另一个进程已被死锁在资源 {%2!} 上,且该事务已被选作死锁牺牲品。请重新运行该事务。

但仍有问题。
1,我在
insert update 后未加任何控制
系统默认加锁
如果3个用户同时执行第一个存储过程
时间分别是
5,10,15S (我用了延时5S)
这是我想要的结果;

2,
在执行第二个存储过程时
如果用系统默认加锁
3个同时执行,有一个会出现
1205,也是死锁
请问怎么查找和避免死锁

3,
如果
insert 和update 及delete
我不想加锁怎么处理

以上所有表都用了 自增长ID
nantian2003 2004-08-01
  • 打赏
  • 举报
回复
不倒就怪
guxing 2004-07-31
  • 打赏
  • 举报
回复
第一个存储过程,有SYS_INF_FQ 、SYS_INF_COMBINE 等存储过程的调用,这时事务已经打开,如果这些存储过程有事务操作,就形成嵌套事务,存储过程内部出错将引起整个事务的失败。

全部改到一个过程中
今天再去客户测试
另外强制加了 with(rowlock)
看看效果
guxing 2004-07-30
  • 打赏
  • 举报
回复
SELECT @iErrorCode=2, @cErrorMessage='拆分F单记录插入子表失败!'
INSERT INTO dt_fdet_out (inid , pid , stanzaid , Auth , Custid , Qbz , Fdet , Amt , PAmt , Accept , DisFdet )
SELECT inid = @iInid ,@iPid , stanzaid , '1' , '99' , Qbz , Fdet , @iLAmt ,@iLPAmt , '1' , DisFdet FROM dt_fdet_out WHERE PID = @Pid AND Amt = @iAmt AND Accept = '2'
IF @@Error<>0 Or @@rowcount < 1
GOTO Error
END

SET @iLAmt = @Amt
SET @iLPAmt = @iPAmt - @iLPAmt


IF @Qbz = '1'
SET @cSamt = 'w'+cast(@iLAmt As varchar(10)) + ' p'+cast(@iLPAmt As varchar(10))
ELSE
SET @cSamt = cast(@iLAmt As varchar(10))
SELECT @iErrorCode=2, @cErrorMessage='修改F单记录表状态失败!'
UPDATE DT_OUTF SET Accept = '1' , AMT = @iLAmt , PAmt = @iLPAmt WHERE PID = @Pid AND Amt = @iAmt AND Accept = '2'
IF @@Error<>0 Or @@rowcount < 1
GOTO Error

UPDATE dt_fdet_out SET Accept = '1' , AMT = @iLAmt , PAmt = @iLPAmt WHERE PID = @Pid AND Amt = @iAmt AND Accept = '2'
IF @@Error<>0 Or @@rowcount < 1
GOTO Error

END

IF @Cbz = '4' /*对机不要,给老板机*/
BEGIN
UPDATE DT_OUTF SET Accept = '1' , Auth ='1' ,Custid ='99' WHERE PID = @Pid AND AMT = @iAmt AND Accept = '2' /*先更改金额,等待重新分配*/
IF @@Error<>0 Or @@rowcount < 1
GOTO Error

UPDATE dt_fdet_out SET Accept = '1' , Auth ='1' ,Custid ='99' WHERE PID = @Pid AND AMT = @iAmt AND Accept = '2'
IF @@Error<>0 Or @@rowcount < 1
GOTO Error
END


IF @Cbz = '1' /* 转分*/
BEGIN
SET @iPid = @Pid
UPDATE DT_OUTF SET Accept = '0' WHERE PID = @Pid AND AMT = @iAmt AND Accept = '2' /*先更改金额,等待重新分配*/
IF @@Error<>0 Or @@rowcount < 1
GOTO Error

UPDATE dt_fdet_out SET Accept = '0' WHERE PID = @Pid AND AMT = @iAmt AND Accept = '2'
IF @@Error<>0 Or @@rowcount < 1
GOTO Error
END

IF @Cbz = '2' /*对机*/
BEGIN
UPDATE DT_OUTF SET Accept = '2' , Custid = '99' , AUTH = '4' WHERE PID = @Pid AND Amt = @iAmt AND Accept = '2'
IF @@Error<>0 Or @@rowcount < 1
GOTO Error

UPDATE dt_fdet_out SET Accept = '2' , Custid = '99' , AUTH = '4' WHERE PID = @Pid AND Amt = @iAmt AND Accept = '2'
IF @@Error<>0 Or @@rowcount < 1
GOTO Error
END


SELECT @iTc = COUNT(*) FROM DT_FDET_OUT WHERE PID = @iPid AND Custid = @Custid AND Accept = '0'
IF @iTc > 0 /* 转分*/
BEGIN
/* 分F过程*/

SELECT @iErrorCode=2, @cErrorMessage='转F插入F单明细记录表失败!'

DECLARE My_C1 CURSOR FOR SELECT Qbz , Fdet , Amt , Pamt , DisFdet FROM DT_FDET_OUT
WHERE PID = @iPid AND Custid = @Custid AND Accept = '0' order by custid
OPEN My_C1
FETCH NEXT FROM My_C1 INTO @cQbz , @cFdet , @iAmt , @iPAmt, @cDisFdet
WHILE (@@FETCH_STATUS <> -1)
BEGIN
IF (@@FETCH_STATUS <> -2)
BEGIN
INSERT INTO DT_FDET_OUT (Inid , Pid, stanzaid , Auth , Custid , Qbz , Fdet , Amt , PAmt , Accept ,DisFdet )
EXEC SYS_OUTF_FQ @stanzaid , @iPid , @cQbz , @cFdet , @iAmt , @iPAmt , @cDisFdet , @iInid/* 拆开F单并插入明细表中过程*/

IF @@Error<>0 Or @@rowcount < 1
GOTO Error

END
FETCH NEXT FROM My_C1 INTO @cQbz , @cFdet , @iAmt , @iPAmt, @cDisFdet
END
CLOSE My_C1
DEALLOCATE My_C1

DELETE DT_OUTF WHERE PID = @iPid AND Custid = @Custid AND Accept = '0'/* 删除以前的单*/
IF @@Error<>0 Or @@rowcount < 1
GOTO Error

DELETE DT_FDET_OUT WHERE PID = @iPid AND Custid = @Custid AND Accept = '0'
IF @@Error<>0 Or @@rowcount < 1
GOTO Error
/*将分开的F单组合并插入DT_OUTF表中*/


SELECT @iErrorCode=2, @cErrorMessage='插入出F单记录表失败!'
INSERT INTO DT_OUTF (Inid , pid , stanzaid , Auth , Custid , Qbz , Fdet , Amt , PAmt ,Accept ,DisFdet )
EXEC SYS_OUTF_COMBINE @iPid , @stanzaid , @Qbz , @Fdet , @iTc, @DisFdet , @iInid/*@Amt*/
IF @@Error<>0 Or @@rowcount < 1
GOTO Error

END /* 分F过程*/

/* 成功返回 */
Success:

COMMIT TRANSACTION
SELECT 'ErrorCode'=0, 'ErrorMessage'=@cSamt

RETURN 0

/* 错误处理 */
Error:
ROLLBACK TRANSACTION
SELECT 'ErrorCode'=@iErrorCode, 'ErrorMessage'=@cErrorMessage

RETURN @iErrorCode
END

RETURN 0
GO


经常是2台机器返回
SELECT @iErrorCode=2, @cErrorMessage='拆分F单记录插入主表失败!'
这个错误

谢谢大家。
我的服务器是
IBM
双至强2。8G,1G内存
会不会是服务器配置低?
guxing 2004-07-30
  • 打赏
  • 举报
回复
这是出第2种错的。

CREATE PROCEDURE DBO.SYS_OUTF
@Pid int , /*Q单ID */
@Cbz char(1) , /*操作类型, '0' -- 自己 , '1' --- 转分 , '2' --- 对机 */
@Qbz char(1) , /*Q单标志 */
@Fdet varchar (20) , /*F单内容 */
@Amt int , /*F金额 */
@DisFdet varchar (50) /*显示F单内容 */
/*WITH ENCRYPTION*/
AS
DECLARE @stanzaid char (2) ; /*场次ID */
DECLARE @Custid char (2) ; /*庄家客户ID */
DECLARE @cQbz char (1) ; /*Q标志 */
DECLARE @cFdet varchar(50) ; /*F单信息 */
DECLARE @cErrorMessage varchar(40) ; /*错误信息 */
DECLARE @iErrorCode int ; /*错误代码 */
DECLARE @Fetch_Status int ; /*游标推进状态 */
DECLARE @iCount int ; /*记录数 */
DECLARE @iAmt int ; /*当前金额 */
DECLARE @iPAmt int ; /*当前P金额 */
DECLARE @iLPAmt int ; /*当前金额 */
DECLARE @rBs decimal(4,2); /*当前WP倍数 */
DECLARE @iLAmt int ; /*当前金额 */
DECLARE @iTc int ; /*完整F单记录数*/
DECLARE @iInid int ;
DECLARE @iPid int ;
DECLARE @iModNum int ;
DECLARE @cDisFdet varchar (50) /*显示F单内容 */
DECLARE @iSlimit int , @iMod int ;
DECLARE @cSamt varchar (50) /*WP金额 */
BEGIN
BEGIN TRANSACTION
SELECT @iErrorCode=2, @cErrorMessage='修改F单记录表状态失败!'
SELECT @iInid = Inid , @stanzaid = stanzaid , @Custid = Custid , @iAmt = Amt , @iPAmt = PAmt FROM DT_OUTF WHERE PID = @Pid AND @Fdet = Fdet AND Accept = '2'
SELECT @iSlimit = Cast(mc as int) FROM BM_BM where lb='10' and bh = '1'/*得到最小限额*/
SET @iLPAmt = 0
IF @Amt < @iSlimit
SET @Amt = @iAmt
SET @rBs = Cast(@iPAmt as decimal(12,2)) / Cast( @iAmt as decimal(12,2))
/* 将分开的F单组合并插入DT_OUTF表中*/

IF @Cbz = '0' /* 自己收*/
BEGIN
IF @iAmt <> @Amt /*要拆分成2单*/
BEGIN
SELECT @iErrorCode=2, @cErrorMessage='拆分F单记录插入主表失败!'

SET @iLAmt = @iAmt - @Amt ; SET @iLPAmt = @iLAmt * @rBs
SET @iLPAmt = DBO.GET_MOD_NUM(@iPAmt , @iLPAmt , @iSlimit)
/*直接去转分*/
SELECT @iPid = Isnull(Max(pid) , 0) + 1 FROM DT_OUTF where stanzaid = @stanzaid
INSERT INTO DT_OUTF (inid , pid , stanzaid , Auth ,Custid , Qbz , Fdet , Amt , PAmt , Accept , DisFdet)
SELECT inid = @iInid , @iPid , stanzaid , Auth , Custid , Qbz , Fdet , @iLAmt , @iLPAmt , '0' , DisFdet FROM DT_OUTF WHERE PID = @Pid AND Amt = @iAmt AND Accept = '2'
IF @@Error<>0 Or @@rowcount < 1
GOTO Error
SELECT @iErrorCode=2, @cErrorMessage='拆分F单记录插入子表失败!'


INSERT INTO dt_fdet_out (inid , pid , stanzaid , Auth , Custid , Qbz , Fdet , Amt ,PAmt , Accept , DisFdet )
SELECT inid = @iInid , @iPid ,stanzaid , Auth , Custid , Qbz , Fdet , @iLAmt ,@iLPAmt , '0' , DisFdet FROM dt_fdet_out WHERE PID = @Pid AND Amt = @iAmt AND Accept = '2'


IF @@Error<>0 Or @@rowcount < 1
GOTO Error
END

SET @iLAmt = @Amt
SET @iLPAmt = @iPAmt - @iLPAmt

IF @Qbz = '1'
SET @cSamt = 'w'+cast(@iLAmt As varchar(10)) + ' p'+cast(@iLPAmt As varchar(10))
ELSE
SET @cSamt = cast(@iLAmt As varchar(10))
SELECT @iErrorCode=2, @cErrorMessage='修改F单记录表状态失败!'

UPDATE DT_OUTF SET Accept = '1' , AMT = @iLAmt, PAmt = @iLPAmt WHERE PID = @Pid AND Amt = @iAmt AND Accept = '2'
IF @@Error<>0 Or @@rowcount < 1
GOTO Error

UPDATE dt_fdet_out SET Accept = '1' , AMT = @iLAmt, PAmt = @iLPAmt WHERE PID = @Pid AND Amt = @iAmt AND Accept = '2'
IF @@Error<>0 Or @@rowcount < 1
GOTO Error

END


IF @Cbz = '3' /* 对机自己收*/
BEGIN
IF @iAmt <> @Amt /*要拆分成2单*/
BEGIN
SELECT @iErrorCode=2, @cErrorMessage='拆分F单记录插入主表失败!'
SET @iLAmt = @iAmt - @Amt ; SET @iLPAmt = @iLAmt * @rBs
SET @iLPAmt = DBO.GET_MOD_NUM(@iPAmt , @iLPAmt , @iSlimit)

/*直接去转分*/
SELECT @iPid = Isnull(Max(pid) , 0) + 1 FROM DT_OUTF where stanzaid = @stanzaid
INSERT INTO DT_OUTF (inid , pid , stanzaid , Auth ,Custid , Qbz , Fdet , Amt , PAmt , Accept , DisFdet)
SELECT inid = @iInid , @iPid , stanzaid , '1' , '99' , Qbz , Fdet , @iLAmt , @iLPAmt , '1' , DisFdet FROM DT_OUTF WHERE PID = @Pid AND Amt = @iAmt AND Accept = '2'
IF @@Error<>0 Or @@rowcount < 1
GOTO Error
guxing 2004-07-30
  • 打赏
  • 举报
回复
谢谢,
这是出第一种错误的
没有返回错误信息,但数据丢失。

CREATE PROCEDURE DBO.SYS_INF
@stanzaid char (2) , /*场次ID */
@Compid char (2) , /*电脑ID */
@Custid char (2) , /*客户ID */
@Qbz char(1) , /*Q单标志 */
@Fdet varchar (20) , /*F单内容 */
@Amt int , /*F金额 */
@PAmt int , /*F单P金额 */
@DisFdet varchar (50) /*显示F单内容 */
/*WITH ENCRYPTION*/
AS
DECLARE @iLen int , @i int , @iLenLoop int , @iLoop int , @iPid int , @iTc INT;
DECLARE @cFed varchar (50) , @cF char(1) , @cDisFed varchar (50) , @cFo char(1) , @chF varchar(2);
DECLARE @cErrorMessage varchar(40), @iErrorCode int, @Fetch_Status int, @Error int , @iCount int;
BEGIN
BEGIN TRANSACTION
SELECT @iErrorCode=2, @cErrorMessage='插入F单记录表失败!'
INSERT INTO DT_INF (stanzaid , Compid , Custid , Qbz , Fdet , Amt , PAmt , DisFdet )
VALUES (@stanzaid , @Compid , @Custid , @Qbz , @Fdet , @Amt ,@PAmt , @DisFdet)
IF @@Error<>0 Or @@rowcount <> 1
GOTO Error
SELECT @iPid = SCOPE_IDENTITY()
CREATE TABLE #DT_FDET ( pid int Not null , Qbz char(1) not null, Fdet varchar (20) NOT NULL , RFdet varchar (20) NULL , Amt INT NULL , PAmt INT NULL default 0)
--SELECT @iPid = Max(ID) FROM DT_INF WHERE stanzaid = @stanzaid AND Compid = @Compid AND Custid = @Custid AND Qbz = @Qbz AND Fdet = @Fdet AND Amt = @Amt
/* 分F过程*/
SELECT @iErrorCode=2, @cErrorMessage='插入F单明细记录表失败!'
SET @iLen = LEN(@Fdet)
SET @i = 0 ; SET @iTc = 0
IF @Qbz = '0' Or @Qbz = '1'/*W , WP */
BEGIN
SET @iLen = @iLen - 3
IF @Qbz = '1'
SET @iLen = @iLen - 1
WHILE @i < @iLen
BEGIN
SET @i = @i + 1 ; SET @iTc = @iTc + 1
SET @cFed = SUBSTRING( @Fdet , @i , 1)
SET @cDisFed= DBO.Con_HEX_NUM(@cFed)
INSERT INTO DT_FDET_IN (pid , stanzaid , Compid , Custid , Qbz , Fdet , Amt , PAmt, DisFdet)
VALUES (@iPid , @stanzaid , @Compid , @Custid , @Qbz , @cFed , @Amt ,@PAmt , @cDisFed )
IF @@Error<>0 Or @@rowcount <> 1
GOTO Error

INSERT INTO DT_FDET_OUT ( stanzaid , Auth , Custid , Qbz , Fdet , Amt , PAmt, Accept , DisFdet , Inid)
EXEC SYS_INF_FQ @stanzaid , @Qbz , @cFed , @Amt , @PAmt , @cDisFed , @iPid /* 拆开F单并插入明细表中过程*/
IF @@Error<>0 Or @@rowcount < 1
GOTO Error
END
END
ELSE IF @Qbz = '2'/*拖 */
BEGIN
SET @i = CHARINDEX ('-' , @Fdet , 1)
SET @cF = LEFT( @Fdet , 1) ; SET @chF = LTRIM(DBO.Con_HEX_NUM(@cF))
WHILE @i < @iLen
BEGIN
SET @i = @i + 1 ; SET @iTc = @iTc + 1
SET @cFo = SUBSTRING( @Fdet , @i , 1)
SET @cDisFed= @chF + '-' +DBO.Con_HEX_NUM(@cFo)
SET @cFed = @cF + '-' + @cFo
INSERT INTO DT_FDET_IN (pid , stanzaid , Compid , Custid , Qbz , Fdet , Amt , PAmt , DisFdet)
VALUES (@iPid , @stanzaid , @Compid , @Custid , @Qbz , @cFed , @Amt ,@PAmt , @cDisFed )
IF @@Error<>0 Or @@rowcount <> 1
GOTO Error
INSERT INTO DT_FDET_OUT ( stanzaid , Auth , Custid , Qbz , Fdet , Amt , PAmt, Accept , DisFdet , Inid)
EXEC SYS_INF_FQ @stanzaid , @Qbz , @cFed , @Amt , @PAmt , @cDisFed , @iPid /* 拆开F单并插入明细表中过程*/
IF @@Error<>0 Or @@rowcount < 1
GOTO Error
END
END
ELSE /* 复式 */
BEGIN
SET @iLen = @iLen - 3
SET @iLenLoop = @iLen
SET @iLoop = 0
WHILE @iLoop < @iLenLoop
BEGIN
SET @iLoop = @iLoop + 1
SET @i = @iLoop
SET @cF = SUBSTRING( @Fdet , @i , 1) ; SET @chF = LTRIM(DBO.Con_HEX_NUM(@cF))
WHILE @i < @iLen
BEGIN
SET @i = @i + 1 ; SET @iTc = @iTc + 1
SET @cFo = SUBSTRING( @Fdet , @i , 1)
SET @cDisFed= @chF + '-' + DBO.Con_HEX_NUM(@cFo)
SET @cFed = @cF + '-' + @cFo
INSERT INTO DT_FDET_IN (pid , stanzaid , Compid , Custid , Qbz , Fdet , Amt , PAmt , DisFdet)
VALUES (@iPid , @stanzaid , @Compid , @Custid , @Qbz , @cFed , @Amt ,@PAmt , @cDisFed)
IF @@Error<>0 Or @@rowcount <> 1
GOTO Error

INSERT INTO DT_FDET_OUT ( stanzaid , Auth , Custid , Qbz , Fdet , Amt, PAmt , Accept , DisFdet , Inid)
EXEC SYS_INF_FQ @stanzaid , @Qbz , @cFed , @Amt , @PAmt , @cDisFed , @iPid /* 拆开F单并插入明细表中过程*/
IF @@Error<>0 Or @@rowcount < 1
GOTO Error
END
END
END /* 分F过程*/

/*将分开的F单组合并插入DT_OUTF表中*/
SELECT @iErrorCode=2, @cErrorMessage='插入出F单记录表失败!'
INSERT INTO DT_OUTF (pid, stanzaid , Auth , Custid , Qbz , Fdet , Amt , PAmt, Accept , DisFdet , Inid )
EXEC SYS_INF_COMBINE @stanzaid , @Qbz , @Fdet , @iTc , @DisFdet , @iPid
IF @@Error<>0 Or @@rowcount < 1
GOTO Error

/* 将分开的F单组合并插入DT_OUTF表中*/

/*检查F单分F是否正确r*/
SET @iErrorCode = -9 ; SET @cErrorMessage = '检测分F失败'
EXEC SYS_CHECK @Inid = @iPid , @Ret = @i OUTPUT
IF @i <> 0
GOTO Error
/* 检查F单分F是否正确r*/
/* 成功返回 */
Success:

COMMIT TRANSACTION
SELECT 'ErrorCode'=0, 'ErrorMessage'=''

RETURN 0


/* 错误处理 */
Error:
ROLLBACK TRANSACTION
SELECT 'ErrorCode'=@iErrorCode, 'ErrorMessage'=@cErrorMessage

RETURN @iErrorCode
END
guxing 2004-07-30
  • 打赏
  • 举报
回复
这里肯定有纪录,没记录不会调用的
谢谢
zjcxc 2004-07-30
  • 打赏
  • 举报
回复
1.楼主把代码帖出来,具体做那些处理的时候出错,看大家能否据此分析


2.楼主自己跟踪一下,看能否据此分析原因
开始--程序--MS SQLSERVER
--事件探察器(SQL Profiler)
--文件
--新建--跟踪...
--设置要跟踪的服务器的信息(连接服务器)--确定
--设置跟踪的项目...
--然后数据库的调用情况就会显示出来

在跟踪项目设置中,如果不熟悉的话,一般用默认设置
筛选项目有几个可以注意一下:

1.DatabaseName 同于你要检测的数据库名
2.Error 同于错误,如果经常出现某个编号的错误,则针对此错误号
3.Seccess 同于0,失败,1,成功,如果是排错,就过滤掉成功的处理
zonelive 2004-07-30
  • 打赏
  • 举报
回复
把代码帖出来大家帮你参详一下,要不不好回复
pengda1i 2004-07-30
  • 打赏
  • 举报
回复
最好贴出简化了的存储过程代码,要能表示出事务的结构

pengda1i 2004-07-30
  • 打赏
  • 举报
回复
第二个存储过程:

SELECT inid = @iInid , @iPid , stanzaid , '1' , '99' , Qbz , Fdet , @iLAmt , @iLPAmt , '1' , DisFdet FROM DT_OUTF WHERE PID = @Pid AND Amt = @iAmt AND Accept = '2'
IF @@Error<>0 Or @@rowcount < 1
GOTO Error

这里Or @@rowcount < 1是不是有问题,因为可能FROM DT_OUTF WHERE PID = @Pid AND Amt = @iAmt AND Accept = '2' 返回0条记录,这时没有数据插入,是不是保证有记录返回呢?
zheninchangjiang 2004-07-30
  • 打赏
  • 举报
回复
UP
pengda1i 2004-07-30
  • 打赏
  • 举报
回复
第一个存储过程,有SYS_INF_FQ 、SYS_INF_COMBINE 等存储过程的调用,这时事务已经打开,如果这些存储过程有事务操作,就形成嵌套事务,存储过程内部出错将引起整个事务的失败。


wzjcntlqs 2004-07-30
  • 打赏
  • 举报
回复
还好,只是晕没有倒!!!
langmafeng 2004-07-30
  • 打赏
  • 举报
回复
帮顶!
herofour444 2004-07-30
  • 打赏
  • 举报
回复
真晕了,这么长
icewen 2004-07-30
  • 打赏
  • 举报
回复
jlam 2004-07-30
  • 打赏
  • 举报
回复

27,579

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 应用实例
社区管理员
  • 应用实例社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧