zoukankan      html  css  js  c++  java
  • 【生产问题】--8KW的数据表导致业务卡顿

    问题描述:业务突然变得巨卡

    分析思路:

      (1)分析用户请求进程:查看是否有长期运行霸占锁的情况,或者进程数量巨多。很明显我这里就是巨多,正常情况一般0~40来个的样子,在业务使用高峰期居然达到了140多个。且等待类型大多为WRITELOG与PAGEIOLATCH_SH(参考:https://www.cnblogs.com/gered/p/9359266.html),意思是写日志等待和系统同步资源被占用需要等待共享锁释放(这里个人很明显感觉是因为查询时间太久,共享锁不释放)导致写入、查询等操作被阻塞在队列里面。下图已经是正常情况,这里做个例子。

       很明显,这里的很多都是重复的,我就大概挑了10条 text的内容,发现多达3-4条是对同一个表操作。

       或许我们可以初步判定其就是导致阻塞的语句;果不然,我试了一下,基于userid查询一条语句,很慢。超过5S,慢的甚至达到了20~30S如果多个用户访问,那么很明显,一人查一个基本就炸毛了,怪不得业务进不来,进程全阻塞在这里,你获取初始化信息的数据的语句都卡在这里。

    (2)查看进程阻塞

      

      列很多,这里没有列全名,最重要的无非就是三个列。 blocking_session_id '阻塞进程的ID', wait_duration_ms '等待时间(毫秒)', session_id '(会话ID)' 

      可以查看是哪个进程在阻塞,但很明显,在高峰期业务卡顿的时候,这里每运行一遍session几乎都会变,不变的多运行几次就变了,也就意味着有阻塞,但是几秒内又变成另外一个进程来阻塞大多数进程了。这也很符合我们的业务,这个用户查的慢,那么几秒过后查完了,其他的用户一个一个堵过来,形成一个恶性循环,互相等待。所以,目前用这个分析,没什么用。

    (3)查看表数据行

      在(1)中,我查询到了出现次数比较多的表,那么我想去看看它多大,有多少数据,先看数据行吧;

      

      看了一下,其实也就8KW多数据,不多啊,为什么会这么慢呢??

      然后我们查查看其表及索引大小

      

      很明显,该表大小达到了近20G,再用其他办法看看

      

      这,索引有点大,那么,我们再来查查看其表结构情况。

      

      怪不得这么大,就4列,这索引不太科学,而且,userid和giftBag重复率很高,尤其以userid最高。

      所以这就是为什么根据userid查询这张表数据这么慢的原因,索引userid列重复数据太多,那么这种索引设置很明显是有问题,如果是小数据量,那还好,一旦到达了5QW以上级别(不知道为什么sql server2005 这种设置到8kw的时候就卡,其他业务数据在3-4KW的时候并没有问题)

      

    问题总结:

      1.表数据查询太慢:原因是数据量大,索引设置不合理

      2.业务数据卡死:由于1中查询出的数据量太大,占用大量数据缓存,导致很多常用数据缓存被迫杀死,常用数据查询时就需要重新执行,然后又会把相应的1中数据杀死,往返循环,导致业务卡。

     制定解决方案

       【1】在线删除:保证业务能正常运行的情况下,我试了试,1-2个小时才删除30W数据,可想而知,我要删到5KW,或者删到我需要保留的业务数据记录行数去,那我估计早就滚蛋了。

       【2】停业务删:我指定的策略是,我需要保存的有效数据量才20W左右,把其插入一个中间表,然后truncate原表/drop 原表,然后把中间表的数据插回原表/把中间表改名成原表名。然后如果是truncate到这里就OK了,重启一下sql server服务引擎(会自动清掉内存)。如果是删除表,这里还需要重新创建索引(感觉这会引起大量的页迁移和变动)。所以我还是选择了truncate模式吧。

      

     --筛选出有效数据  

    ;with temp1 as (
    select * from db_tank..GMActive_UserAward(nolock)

    where lastAwardTime >= '20180508'
    )

    --备份有效数据到中间表
    select * into db_del..temp_GMActive_userAward from temp1
    --截断原8KW数据的表
    truncate table db_tank..GMActive_UserAward

    --把中间表插回去
    insert into db_tank..GMActive_UserAward select * from db_del..temp_GMActive_userAward

    --验证

    --select * from db_tank..GMActive_UserAward where userid = 557370617
    --sp_help GMActive_UserAward

     

      

    --分析用户进程
    select status,start_time,command,percent_complete,wait_type,text,
    session_id,blocking_session_id
    from sys.dm_exec_requests r
    cross apply sys.dm_exec_sql_text(r.sql_handle) s
    
    --查看进程阻塞
    
    SELECT blocking_session_id '阻塞进程的ID', wait_duration_ms '等待时间(毫秒)', session_id '(会话ID)' 
    select * FROM sys.dm_os_waiting_tasks
    
    --查看表数据有多少行
    
        SELECT   a.name, b.rows
        FROM      sysobjects AS a INNER JOIN
                         sysindexes AS b ON a.id = b.id
        WHERE   (a.type = 'u') AND (b.indid IN (0, 1))
        AND a.name = 'GMActive_UserAward'
        ORDER BY b.rows DESC
    
    
    --查看期望有效数据数据量
    select count(1) from GMActive_UserAward(nolock)
    where lastAwardTime >= '20180508'
    
    
    --查看表对应索引数据空间
    SELECT
        i.name                  AS IndexName,
        SUM(s.used_page_count) * 8/1024   AS IndexSizeMB
    FROM sys.dm_db_partition_stats  AS s 
    JOIN sys.indexes                AS i
    ON s.[object_id] = i.[object_id] AND s.index_id = i.index_id
    WHERE s.[object_id] = object_id('dbo.GMActive_UserAward')
    GROUP BY i.name
    ORDER BY i.name
    
    --查看表使用空间
    exec sp_spaceused GMActive_UserAward
    
    --查看表对应索引数据
    SELECT
        i.name              AS IndexName,
        SUM(page_count * 8) AS IndexSizeKB
    FROM sys.dm_db_index_physical_stats(
        db_id(), object_id('dbo.GMActive_UserAward'), NULL, NULL, 'DETAILED') AS s
    JOIN sys.indexes AS i
    ON s.[object_id] = i.[object_id] AND s.index_id = i.index_id
    GROUP BY i.name
    ORDER BY i.name
  • 相关阅读:
    jdbc读取数据库表
    java中byte和blob互转
    mysql解决错误的方法-MySQL日志
    源码编译配置lnmp部署zabbix
    ssh后门反向代理实现内网穿透
    Cisco、HUAWEI、H3c、Firewall等设备配置snmp
    zabbix通过snmp监控网络设备
    centos/linux扩容Swap分区
    fork炸弹
    解决You have new mail in /var/spool/mail/root提示
  • 原文地址:https://www.cnblogs.com/gered/p/9442239.html
Copyright © 2011-2022 走看看