事务_进程 ID 57_与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运行该事务
问题描述
执行下面这个SQL查询语句时,经常会报这个错!事务_进程 ID 57_与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运行该事务
string sql = $@"select distinct
b.F_Barcode as 条码号
,b.F_PatientID as 门诊号
,b.F_Name as 病人姓名
,(case b.F_Sex when '1' then '男' when '2' then '女' else '未知' end) as 性别
,b.F_Age as 年龄
,d2.Name as 样本类型
,b.F_BedNo as 床号
,b.F_CreateDate as 开单时间
,b.F_Transport as 送检医生
,d.F_Name as 开单科室
,b.F_Clinical as 临床诊断
,'' as 项目英文名
,stuff((
select distinct ',' + a.F_Name
from T_LIS_App_Item a
left join T_LIS_Report_Bill r2 on r2.F_ID = a.F_ReportID
left join T_LIS_Base_OrgJob j2 on j2.F_ID = r2.F_WKSID
left join T_LIS_App_Bill b2 on b2.F_SAMID = r2.F_SAMID
where
r.F_Exp2 = r2.F_Exp2 and j2.F_Name like '%迪安%' and r2.F_CheckDT >='{timeStart}' and r2.F_CheckDT <'{timeEnd}'
for xml path('')),1,1,'') as 项目中文名
,b.F_SAMID as 样本号
,ISNULL(r.F_CheckDT,GETDATE()) as 送检日期
,ISNULL(r.F_CheckDT,GETDATE()) as 采样日期
,'' as 标本个数
,'' as 标本要点
,r.F_Exp2 as 迪安条码
,'' as 病人电话
,b.F_DoctorTel as 医生电话
,d1.Name as 病人类型
,'' as 病人身份证
,b.F_Org as 医院名称
from T_LIS_App_Bill b
left join T_LIS_Base_OrgDept d on d.F_ID = b.F_Dept
left join T_LIS_Report_Bill r on r.F_SAMID = b.F_SAMID
left join TB_DictData d1 on d1.DictType_ID = 'DTHZLX' and d1.Value = b.F_PatientSort
left join TB_DictData d2 on d2.DictType_ID = 'DTSampleSort' and d2.Value = b.F_SAMType
left join T_LIS_Base_OrgJob j on j.F_ID = r.F_WKSID
where
r.F_CheckDT >='{timeStart}' and r.F_CheckDT <'{timeEnd}'
and r.F_Exp2 is not null
and j.F_Name like '%迪安%'
{and}
order by r.F_Exp2 asc";
原因分析:
虽然这个错误提示是由于竞争资源引起的,但根本原因在我看来还是由于SQL语句中带有stuff函数,导致消耗了太多时间导致更容易引起竞争资源。
所以优化的根本还是在于要优化SQL语句本身,减少消耗时间。
解决方案:
删除Stuff函数,改用代码的方式运算。
Stuff函数固然可以节省很多代码,但同时,消耗的时间也是及其恐怖,消耗时间多可能是由于业务表数据量大引起的,但也从侧面说明了这个函数也是比较耗时的。
在实际使用过程中,还是尽量避免使用这类函数,改用代码处理,速度可以算是天壤之别。