1
bwd1991 OP 求帮助 要通宵了 o(╥﹏╥)o
|
2
chuckzhou 2021-03-29 19:05:30 +08:00
你是用的 sql 还是 oracle ?
|
3
chuckzhou 2021-03-29 19:06:14 +08:00
哦,sql,开 profiler 看了吗
|
5
redtea 2021-03-29 19:12:46 +08:00
看到 his 就想到夏某某破坏医疗领域提供公共服务的计算机信息系统,被判刑 5 年多。
|
6
zjlin1984 2021-03-29 19:13:27 +08:00
估计你的 sql 查询很耗资源
|
11
bwd1991 OP @chuckzhou 会和索引的 PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF
这些属性有关系吗 |
12
dswyzx 2021-03-29 19:21:48 +08:00
|
13
chuckzhou 2021-03-29 19:32:27 +08:00
@bwd1991 ALLOW_ROW_LOCKS 和 ALLOW_PAGE_LOCKS 改成 on 试试,一般这个都打开的。
|
16
Leigg 2021-03-29 20:26:34 +08:00 via Android
不要说废话,直接贴日志。
|
17
bwd1991 OP @chuckzhou 下面的函数和一个单条更新语句
ALTER PROCEDURE [dbo].[GetIcCardBalance] @sID varchar(12), @balance decimal(10,2) out AS BEGIN set @balance = 0 set @balance = (select isnull(balance,0) from ic_register (NOLOCK) where patient_id = @sID) - isnull((select sum(isnull(charge_price * charge_amount*caoyao_fu,0)) from mz_detail_charge WITH (nolock) where patient_id = @sID and charge_status = '2'),0) --set @balance = dbo.GetICRealBalance(@sID) if @@error = 0 return 0 else return -1 END |
19
ferock 2021-03-29 21:28:50 +08:00 via iPhone
|
22
Anybfans 2021-03-29 22:44:08 +08:00 via iPhone
看下这个字段的数据类型 charge_status 。是不是有隐式数据类型转换
|
23
gBurnX 2021-03-29 22:48:06 +08:00 1
两个原因:
1.出现死锁,先看硬件负载。如果硬件负载高,有可能是某个操作需要锁表,同时还需要消耗大量硬件资源,那么在该操作完成前,其他操作会因为锁而竞争或排队,造成假死锁的现象。这种事情可以通过等待来解决。 这个阶段主要看看 CPU 使用率、内存使用率、磁盘活动时间、网络带宽使用率。解决方案是,哪个硬件使用率太高,就升级该硬件。比如,如果磁盘活动时间一直为 100%,而且用的是机械硬盘,那么换 SSD 甚至 M.2 NVME 协议的一线品牌的 SSD 。 2.如果死锁但各硬件负载很低,那么很有可能是出现互相锁住的问题了。解决这个问题,是一件体力活。方法如下: 在程序代码、数据库存储过程或函数等存在代码的位置,以 [Lock] 不区分大小写的方式,找出所有锁定语句所涉及的表名,在 Excel 里把这些表名称列出来。不区分大小写的意思是,有些地方可能是 lock,有些地方可能是 LOCK,或 Lock 等等。 然后把这些表名,在 Excel 里设置一个顺序。比如,在 Excel 里,设置了顺序为: 1 TableA 2 TableB 3 TableC 意思是,先锁 TableA,再锁 TableB,最后锁 TableC 。 按照这个顺序,修改所有涉及到 Lock 的地方。 比如,你发现某个存储过程,锁定顺序为: ...... SELECT * FROM TableC With (TabLockX) WHERE id = 3 ...... SELECT * FROM TableB With (TabLockX) WHERE id = 2 ...... 该存储过程先锁了 TableC,然后再锁了 TableB,这种锁定顺序违背了 Excel,因此调整为: ...... SELECT * FROM TableB With (TabLockX) WHERE id = 2 ...... SELECT * FROM TableC With (TabLockX) WHERE id = 3 ...... 调整时注意不能改变业务逻辑。如果改变了业务逻辑,需要按照 Excel 的锁定顺序,重新实现该存储过程。 把所有涉及到锁的代码或存储过程或函数等,按照这种方式,全部修改,修改完毕后,锁问题应该能解决了。 |
25
bwd1991 OP @gBurnX 硬件应该不会 cpu 20%以下 内存不过半
主要是之前一直没有问题 今天突然这样了 有什么原因会导致这样吗 没有升级程序,数据库也没动过 |
26
xioxu 2021-03-29 23:23:28 +08:00
1. 用 sql profiler 抓取死锁相关日志,查看引起死锁的语句
2. 分析引起死锁的代码,看是否存在争抢资源的可能(一般是肯定存在),否则不会死锁 3. 修改代码对同一资源的获取顺序,保持一致(以规避死锁) |
27
xioxu 2021-03-29 23:25:37 +08:00
@bwd1991 问题突发的原因有很多,譬如数据量现在上去了、索引碎片... 导致死锁概率增大,本质上还是代码就有死锁问题导致的
|
29
leeg810312 2021-03-29 23:58:18 +08:00 via Android
死锁通常都是代码逻辑问题。估计你们的 HIS 有些操作是跨好几个表的事务,可能是部分表数据量大了,事务运行时间较长,且事务中还有查询操作,这样在大量请求并发时,很容易产生表锁竞争导致死锁。建议按以下排查
1 、死锁表的数据量是否较大,代码中的 sql 是否较慢,数据量到几百万上千万或更多,优化索引,同时考虑做分区或分表 2 、检查代码中的跨多表事务,尽量在事务外做查询,尽可能减少跨表事务的数量,尽可能缩减跨表事务的跨表范围,整体上降低多表锁竞争的概率 3 、没有触发器和存储过程是最好,有的话都改在代码里实现。这 2 个都是测试困难户,写在数据库里很容易被忘记,也容易让数据产生代码预期外的结果。喜欢存储过程的人倾向写很长跨多表的存储过程,调试起来及其麻烦,且高并发时非常容易产生死锁 |
30
Fule 2021-03-30 00:10:09 +08:00
你的 `mz_detail_charge` 表里有多少字段?如果远多于 `charge_price`, `charge_amount`, `caoyao_fu`, `patient_id`和`charge_status`,那么试试创建一个覆盖索引:
``` CREATE INDEX IX_mz_detail_charge_price_amount_caoyao_fu ON mz_detail_charge ( patient_id ASC, charge_status ASC ) INCLUDE ( charge_price, charge_amount, caoyao_fu ) WITH ( PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON ) ``` |
31
realpg 2021-03-30 00:12:17 +08:00
就是互锁了
报 BUG,让开发改 否则无解 |
32
gBurnX 2021-03-30 01:24:19 +08:00
@bwd1991
1.不要拍脑袋说硬件应该不会。CPU 、内存、网络用任务管理器去查,磁盘活动时间用资源监视器去查。做事情要仔细,要落地。 2.不要说什么以前没问题,现在突然有问题。只要系统有 bug,什么时候被你们发现,都有可能。bug 发作有早有晚,而且说不定早发作了,只是大家没发现或并不明显。 3.你现在要做的,就是按照我在 23 楼,第 2 点给出的具体方案去进行修改。按这方案你肯定会发现一堆锁定顺序相反的操作 SQL |
33
cnzjl 2021-03-30 07:05:08 +08:00
看到这个问题,我以为咱俩是同事
|
34
bwd1991 OP @gBurnX 1 、cpu 不到 10% 内存还剩 100G 磁盘读取有问题 巅峰额能到 70-80G
2 、 我们没有源码 只能 sql 跟踪语句 能处理的都处理了 ,我说之前没问题是想问问有什么情况突然导致这样吗,是全库重建索引还是怎么着 |
36
zjlin1984 2021-03-30 08:32:48 +08:00
1. with nolock 先试试
2. 把相关的 sql 语句找出来,看看有没有 join,再看看逻辑读写的次数多少,where 语句的过滤条件是不是都在索引里面。 |
37
gBurnX 2021-03-30 13:33:11 +08:00
|
38
thtznet 2021-03-30 16:49:03 +08:00
2021 年了,系统可以更新下了,不要面向数据库表开发,建领域模型,用 ORM 。虽然 ORM 可能效率不是极致的优化,但是比大部分草台班子手写 SQL 还是要靠谱点。
|