数据库查询超时,并发问题处理

当执行sql长时间未响应,数据库返回超时时,我们应该去查询是谁导致的超时。

首先分析你的sql语句查询或修改时有没有使用索引,或者当前操作的表是否数据量太大,又或是字段太多?

如果以上都没问题,然后再查询是因为什么造成的阻塞导致超时

sql 复制代码
SELECT 
    wt.session_id AS waiting_session_id,
    wt.wait_duration_ms,
    wt.wait_type,
    wt.blocking_session_id,
    wt.resource_description,
    es.program_name AS waiting_program,
    es.host_name AS waiting_host,
    es.login_name AS waiting_login,
    er.status AS waiting_status,
    -- 从 dm_exec_requests 获取 sql_handle(如果存在活动请求)
    sql_text.text AS waiting_sql
FROM sys.dm_os_waiting_tasks wt
JOIN sys.dm_exec_sessions es ON wt.session_id = es.session_id
LEFT JOIN sys.dm_exec_requests er ON wt.session_id = er.session_id
OUTER APPLY sys.dm_exec_sql_text(er.sql_handle) sql_text
WHERE wt.wait_type = 'LCK_M_U';

然后再去查询是谁阻塞的,谁又在等待

sql 复制代码
SELECT 
    ws.blocking_session_id AS blocking_spid,
    bs.login_name AS blocking_login,
    bs.host_name AS blocking_host,
    bs.program_name AS blocking_program,
    -- 获取阻塞者的SQL语句
    COALESCE(
        (SELECT text FROM sys.dm_exec_requests ber CROSS APPLY sys.dm_exec_sql_text(ber.sql_handle) WHERE ber.session_id = bs.session_id),
        (SELECT dest.text FROM sys.dm_exec_connections bec CROSS APPLY sys.dm_exec_sql_text(bec.most_recent_sql_handle) dest WHERE bec.session_id = bs.session_id)
    ) AS blocking_sql,

    ws.session_id AS waiting_spid,
    ws.wait_duration_ms,
    ws.wait_type,
    ws.resource_description,

    -- 获取等待者的SQL语句
    COALESCE(
        (SELECT text FROM sys.dm_exec_requests wer CROSS APPLY sys.dm_exec_sql_text(wer.sql_handle) WHERE wer.session_id = ws.session_id),
        (SELECT dest.text FROM sys.dm_exec_connections wec CROSS APPLY sys.dm_exec_sql_text(wec.most_recent_sql_handle) dest WHERE wec.session_id = ws.session_id)
    ) AS waiting_sql

FROM sys.dm_os_waiting_tasks ws
JOIN sys.dm_exec_sessions bs ON ws.blocking_session_id = bs.session_id
JOIN sys.dm_exec_sessions ws_sess ON ws.session_id = ws_sess.session_id
WHERE ws.blocking_session_id IS NOT NULL;

如果是因为表数据量太大,索引该加的都加了。那去排查表有没有升级锁

当 SQL Server 检测到单个语句获取了 5000+ 行锁,会自动升级为 表锁(TABLE LOCK),导致整个表被锁住!如果整张表被锁了那么查询或修改效率将大大降低

sql 复制代码
--查询表的锁类型
SELECT 
    t.name AS table_name,
     lock_escalation_desc
FROM sys.tables t
WHERE t.name = 'table';  -- 替换为你的表名

--TABLE	默认行为:当行锁 > 5000 或内存压力大时,升级为 整表锁
--DISABLE	禁用锁升级 → 始终使用行/页锁(推荐用于高并发单行更新场景)
--AUTO	(SQL Server 2016+)在分区表上可自动升级到 分区级锁

--我们将锁类型修改为禁用锁升级
ALTER TABLE [table] SET (LOCK_ESCALATION = DISABLE);
相关推荐
天天喝旺仔10 分钟前
Python asyncio 异步编程实战:用协程与事件循环构建高性能网络服务
服务器·网络·python·性能优化·fastapi
运维行者_20 分钟前
ISP 企业级带宽计费怎么做?网络流量计费的 6 大核心能力
运维·服务器·网络·数据库·支持向量机·接口隔离原则
奇树谦25 分钟前
PCB生产制造全流程详解:从开料、钻孔、沉铜到检测、包装
网络·数据库·制造
驾驭人生42 分钟前
Hangfire.Redis.StackExchange 已归档停更!生产任务卡死、重复执行、网络抖动问题解决方案
数据库·redis·缓存
xierui12312344 分钟前
Agent记忆不是聊天记录:用三层存储构建可追溯的 AI 工作流
数据库·人工智能·aigc·软件工程
2301_800074211 小时前
mysql DQL
数据库·sql·mysql
西风未眠1 小时前
ClickHouse数据库引擎引起的数据丢失
数据库·clickhouse·故障
海浪仙人掌1 小时前
应收账款分析如何操作?应收账款分析有哪些注意事项?
数据库·人工智能
Elastic 中国社区官方博客1 小时前
在 Elasticsearch 中回填时间序列数据:通过批量 API 加载数月的历史指标数据
大数据·运维·数据库·人工智能·elasticsearch·搜索引擎·全文检索
Horn Still Sounds1 小时前
Linux网络并发服务器模型与SQLite数据库学习笔记
linux·服务器·数据库