如何捕获锁定/锁定消耗的SPID/进程

2020-08-21 01:28发布

         点击此处--->   EasySAP.com群内免费提供SAP练习系统(在群公告中)

加入QQ群:457200227(SAP S4 HANA技术交流) 群内免费提供SAP练习系统(在群公告中)


嗨,

我有7 TB大小的大型SAP ASE数据库,正在运行数千个作业。 我们在深夜遇到了"锁用尽"问题,很难找到哪个SPID/进程占用了所有锁。

在DBA控制台中找不到哪个会话消耗了所有锁的信息。

在ASE日志中,所有可用的受害会话信息均有效,而并非元凶会话。

请建议我们如何找到作业消耗所有锁的会话,或者将来如何进行监视。

此致

Bhupendra Sharma

         点击此处--->   EasySAP.com群内免费提供SAP练习系统(在群公告中)

加入QQ群:457200227(SAP S4 HANA技术交流) 群内免费提供SAP练习系统(在群公告中)


嗨,

我有7 TB大小的大型SAP ASE数据库,正在运行数千个作业。 我们在深夜遇到了"锁用尽"问题,很难找到哪个SPID/进程占用了所有锁。

在DBA控制台中找不到哪个会话消耗了所有锁的信息。

在ASE日志中,所有可用的受害会话信息均有效,而并非元凶会话。

请建议我们如何找到作业消耗所有锁的会话,或者将来如何进行监视。

此致

Bhupendra Sharma

付费偷看设置
发送
3条回答
浮生未央
1楼-- · 2020-08-21 01:52

你好Bhupendra,

如果并发性很高,很难检查哪一个是导致此问题的罪魁祸首。 一个工作(即数据加载)或用户会话(即报告)需要访问比平常更多的数据。 一些建议:

1)要检查ASE错误日志中报告的第一个错误1204的日期时间,并与SM37进行交叉匹配,以检查哪些作业可能已在该日期时间附近运行。 至少可以帮助减少批处理作业的选择。

2)要从当天的DBACockpit> Performance> SQL语句> Top语句中检查消耗最大的语句(平均经过时间更长),并检查其Details是否在该时间运行 报告了第一个错误1204的位置。 首先,要分析查询是进行表扫描还是访问非常大的表,是否对表进行时间重组等。请确保表重组已经完成(通过ATM)。

3 )还要检查ASE参数"锁数"的值,考虑到您的数据库大小,该值至少应为1500万。 不要犹豫将其增加到2000万,并继续监视ASE错误日志中是否有新的1204,或者您可以在isql会话(包括在crontab shell上)上运行此命令,以查看锁的使用情况不时演变 :

isql -S -Usapsa -X

sp_monitorconfig"锁数"
go

当几乎达到限制时,请检查 从SM50当前会话开始,并通过DBACockpit>性能>进程或使用isql从" select * from master..sysproceses"查询中从ASE中进行检查。

4)设置lock_count资源调控器限制。 您可以参考KBA 2203739 -"错误1204:服务器已失锁并挂起-SAP ASE" 和SAP注意 2224350 -SYB:DBA座舱-为"锁定计数"启用资源限制并支持操作类型 '取消交易'

HTH,

亲切的问候,
维多利亚。

Bunny_CDM
2楼-- · 2020-08-21 01:56

这是我用来监视锁的详细存储过程。 注意,此proc包含额外的代码,可忽略当有人运行" reorg rebuild

"命令时弹出的错误。 该过程还显示偶尔的锁定请求,这些请求实际上还不是锁定(但仍然可以被阻止)。 感谢所有反馈:

使用sybsystemprocs
 走
 创建过程sp_lock2 @verbose int = 0
 如
 开始
   设置兼容性模式
   设置为nocount
   if(@verbose = 0)
   开始
     -如果不详细,则显示每种spid和锁定类型的计数
     选择p.spid,p.status,p.hostname,hostpid = p.hostprocess,p.program_name,p.cmd,BlockedOnSpid = p.blocked,
            object = case when(p.cmd =" REORG"和p.tran_name如"%ALTER TABLE ADM%"和p.tran_name如"%dbid =" + convert(varchar(20),l.DBID)+"%"
                              和p.tran_name,例如"%ID =" + convert(varchar(20),l.ObjectID)+"%"
                             )
                        然后l.DBName +" .." + convert(varchar(20),l.ObjectID)
                        else l.DBName +" .." + object_name(l.ObjectID,l.DBID)
                   结束,
            l.LockID,l.LockState,l.LockType,l.LockLevel,WaitSecs = l.WaitTime,l.BlockedState,BlockedByLockID = l.BlockedBy,cnt = count(*)
     进入#tmp_cnt
     来自master..sysprocesses p,master..monLocks l
     其中p.spid = l.SPID和p.spid!= @@ spid
     -从object_name()过滤出虚假错误消息,例如:
     -数据库''中的对象''正在进行REORG操作。 稍后重试查询。
     -对于在带有w/dbid = 15的数据库中运行" reorg rebuild "的进程,sysprocesses将显示一个tran_name,例如" $ ALTER TABLE ADM  ID = 192000684 dbid = 15 fid = 41"
     按p.spid,p.status,p.hostname,p.hostprocess,p.program_name,p.cmd,p.blocked分组
              (p.cmd =" REORG"和p.tran_name如"%ALTER TABLE ADM%"和p.tran_name如"%dbid =" + convert(varchar(20),l.DBID)+"%"
                              和p.tran_name,例如"%ID =" + convert(varchar(20),l.ObjectID)+"%"
                             )
                        然后l.DBName +" .." + convert(varchar(20),l.ObjectID)
                        else l.DBName +" .." + object_name(l.ObjectID,l.DBID)
                   结束,
              l.LockID,l.LockState,l.LockType,l.LockLevel,l.WaitTime,l.BlockedState,l.BlockedBy


     exec sp_autoformat @fulltabname =" #tmp_cnt",
                        @selectlist =" spid,状态,主机名,hostpid,程序名,cmd,BlockedOnSpid,对象,LockID,LockState,LockType,LockLevel,WaitSecs,BlockedState,BlockedByLockID,cnt",
                        @orderby ="按spid,状态,主机名,hostpid,program_name,cmd,BlockedOnSpid,object,LockID,LockState,LockType,LockLevel进行排序"
     删除表#tmp_cnt
   结束
   其他
   开始
     -对于详细输出,显示每个页面/行的锁定并显示SourceCodeID
     选择p.spid,p.status,p.hostname,hostpid = p.hostprocess,p.program_name,p.cmd,BlockedOnSpid = p.blocked,
            object = case when(p.cmd =" REORG"和p.tran_name如"%ALTER TABLE ADM%"和p.tran_name如"%dbid =" + convert(varchar(20),l.DBID)+"%"
                              和p.tran_name,例如"%ID =" + convert(varchar(20),l.ObjectID)+"%"
                             )
                        然后l.DBName +" .." + convert(varchar(20),l.ObjectID)
                        else l.DBName +" .." + object_name(l.ObjectID,l.DBID)
                   结束,
            l.LockID,l.LockState,l.LockType,l.LockLevel,WaitSecs = l.WaitTime,l.BlockedState,BlockedByLockID = l.BlockedBy,l.PageNumber,l.RowNumber,l.SourceCodeID
     进入#tmp
     来自master..sysprocesses p,master..monLocks l
     其中p.spid = l.SPID和p.spid!= @@ spid
     exec sp_autoformat @fulltabname =" #tmp",
                        @selectlist =" spid,状态,主机名,hostpid,program_name,cmd,BlockedOnSpid,对象,LockID,LockState,LockType,LockLevel,WaitSecs,BlockedState,BlockedByLockID,PageNumber,RowNumber,SourceCodeID",
                        @orderby ="按spid,状态,主机名,hostpid,program_name,cmd,BlockedOnSpid,object,LockID,LockState,LockType,LockLevel进行排序"
     删除表#tmp
   结束
 结束
 走

 

此外,现在是否有发布此类共享代码的地方? (也许在github上?)

SKY徐
3楼-- · 2020-08-21 01:54

要快速进入SPID,我在monProcessActivity中使用LocksHeld。

如果您根据需要频繁轮询-例如 我每分钟都在使用-,您可以将消耗锁的顶级SPID归零。 在某些情况下,使用的锁可能呈指数级攀升。

我有一个看门狗进程,可以杀死任何一个spid抓取超过一半配置值的spid(例如,在我的情况下,配置2M的1M锁)

其他表格也可以用来补充您找到的内容。 但是有些需要实现,例如 sysprocesses + tempdb空间,其他可能有太多行,例如 monLock可以快速通过。

HTH

Avinash

一周热门 更多>

向帮助了您的网友说句感谢的话吧!