Sybase 数据库中自旋锁和CPU使用率

翻译整理自文章《Spinlocks and CPU usage in SAP ASE》

目的

这篇文章的目的是清楚的了解SAP ASE怎样使用自旋锁及对整体CPU使用率可能产生的影响。

简介

通常,SAP ASE中CPU高可以归因为自旋锁的使用。这篇文章将要展示怎样识别这些条件和推荐的ASE调优方法。

什么是自旋锁?

  • 在一个多引擎的服务中需要使用同步机制保护共享资源。
    ASE使用自旋锁作为它同步机制的一种
    自旋锁是一种只能被原子性更新的数据结构(就是在同一个时刻只能有一个引擎修改它)

  • 当一个任务修改一个共享的数据项,它必须先持有自旋锁。
    共享数据项是类似于运行队列、数据缓存页列表、锁结构等

  • 自旋锁阻止同一时刻另外一个任务修改它的值。
    这当然是假设另外一个任务也在自旋锁的保护机制下执行访问

  • 一个需要获取自旋锁的任务在被授予之前将要“自旋”(阻塞)
    当同一时刻多个引擎在自旋时CPU使用率会大大升高

  • 自旋锁必须尽可能的快和高效
    为了减小竞争一个进程通常在不断的循环请求和释放他的自旋锁
    因此自旋锁使用平台相关的汇编语言编写

自旋锁和其他同步机制的比较

类型 复杂度 CPU 开销 等待时间
自旋锁 非常低
闩锁 中等 比较小
表、页、行地址锁 可能有很大差别

自旋锁和CPU 使用率

  • spid 在获取自旋锁之前不会让出引擎
    所以一个正在等待自旋锁的spid,在获取这个自旋锁之前会引起该引擎用户态100%

  • 自旋锁竞争百分比是用等待/抢占来度量的
    比如:10000抢占中3000次等待=30% 竞争

  • 为了查找性能问题,使用总自旋数,不是竞争比
    比如:两个自旋锁

    1. 一个100次抢占中40次等待但是200次自旋 = 40% 竞争
    2. 第二个10000次抢占中400次等待但是20000次自旋 = 4%竞争

    第二个虽然竞争度很低,但是使用了更多CPU周期自旋。
    我们应该关注第二个例子的调优,而不是第一个。

解决自旋锁问题

  • 自旋锁的竞争和自旋是CPU高的一个主要原因
  • 第一步是判断实际上CPU高是不是由自旋锁使用引起的。
  • 第二步是判断哪一个或哪一些自旋锁引起了这种情况。
  • 第三步是判断使用哪种调优来减小这个问题。

注意 你永远也不可能得到0%自旋锁竞争除非在只有一个引擎的服务上运行。就是说,不要去想消除自旋锁竞争。它只能被尽可能的减小。

第一步 - 检查自旋锁竞争和自旋

  • 使用sp_sysmon去判断是否CPU高是因为自旋锁
  • 检查“CPU Busy”(或者“User Busy” 在15.7线程模式中)。
  • 如果引擎没有显示出高busy%那么自旋锁不是一个大问题。
  • 在“Data Cache Management”中检查"Total Cache Hits"
    如果每秒缓存命中率高并且和cpu busy%一起上升,那么你应该查找全表扫描和查询计划问题而不是自旋锁。
  • 通常,如果CPU使用率增加但是事务提交量、缓存命中数、锁请求数、扫描数等在下降,那么自旋锁使用可能是一个问题。

第二步 - 哪一个或哪一些自旋锁引起竞争?

  • 使用sp_sysmon
  • 这里列出了几种自旋锁,但是只展示了竞争百分比
  1. Object Manager Spinlock Contention
  2. Object Spinlock Contention
  3. Index Spinlock Contention
  4. Index Hash Spinlock Contention
  5. Partition Spinlock Contention
  6. Partition Hash Spinlock Contention
  7. Lock Hashtables Spinlock Contention
  8. Data Cache Spinlock Contention
  • 这些中的任何一个竞争高可能暗示一个问题
    但是,你可能有其他的自旋锁竞争并没有在sp_sysmon报告中显示

  • 使用MDA表 monSpinlockActivity
    这张表在15.7 ESD#2版本加入

  • 使用标准SQL查询
    一个根据一分钟间隔内的自旋次数展示前10条自旋锁的查询可能是这样的

   select * into #t1 from monSpinlockActivity
   waitfor delay "00:01:00"
   select * into #t2 from monSpinlockActivity
   select top 10 convert(char(30),a.SpinlockName) as SpinlockName,
   (b.Grabs - a.Grabs) as Grabs,(b.Spins - a.Spins) as Spins,
   case when a.Grabs = b.Grabs then 0.00 else convert(numeric(5,2),(100.0 * (b.Waits - a.Waits))/(b.Grabs-a.Grabs)) end as Contention 
   from #t1 a,#t2 b where a.SpinlockName = b.SpinlockName 
   order by 3 desc   

使用monSpinlockActivity可能的问题

  • 多个引擎的自旋锁将被聚集计算
    例如,所有的数据缓存分区自旋锁将被显示成一行
    这可能使仅一个缓存分区引起问题的情况不能被发现
  • 必须设置'enable spinlock monitoring' 配置参数
    测试显示对于繁忙的服务这又增加了大约1%的开销
  • monSpinlockActivity 显示当前和最后一个拥有者的KPIDs。这可能是有用的对检查的进程是否是造成特定自旋锁。

第三步 - 做什么调优会对减小这个问题

  • 这要依据哪些自旋锁是高度自旋的大量判断
  • 注意这也有可能降低了一个自旋锁的竞争然后又增加了另一个

一些更通用的自旋锁和可能的解决办法

  • Object Manager Spinlock(Resource ->rdesmgr_spin)

    1. 确定配置了充足的'number of open objects'
    2. 用monOpenObjectActivity识别热点对象
    3. 使用 dbcc ture(des_bing)将热点对象绑定到DES缓存
    4. 修改起作用的原因是用来保护DES 不被使用的自旋锁知道确切数目。当DES被绑定整个进程将跳过。
  • Data Cache spinlocks

    1. 减少data cache spinlock 利用率最简单的方法是增加data cache 分区的数量。
    2. 注意如果data cache 被设置成了"relaxed LRU",自旋锁使用率可能会大幅减小。这是因为relaxed LRU缓存不用维护LRU->MRU链,所以不需要抢占自旋锁去移动页到MRU端。
    3. 有一些定义条件使用这个帮助(一个周转率非常高的缓存是不适合relaxed LRU的)
  • Procedure Cache Spinlock (Resource ->rproccache_spin)

    1. 从全局过程缓存内存池(包括语句缓存)中分配和释放页需要是用自旋锁。
    2. 一些可能的原因包括:
      过程缓存太小, 存储过程和语句经常被移出和替换
      存储过程重新编译
      Large scale 分配
    3. 减小这个自旋锁的压力
    4. 消除存储过程重新编译的原因
    5. 如果运行一个比ASE 15.7ESD#4低的版本,需要升级。ASE 15.7 ESD#4和4.2有一些修改,减小了持有自旋锁的时间。
    6. trace flags 753和757可以减小 large-scale的分配
    7. 在ASE15.7 SP100之后的版本,使用配置参数"enable large chunk elc"
    8. 使用dbcc proc_cache(free_unused) 作为临时的减小自旋锁和CPU使用率的方法。
  • Procedure Cache Manager Spinlock( Resource ->rprocmgr_spin)

    1. 动态SQL和存储过程进入和移出过程缓存时使用自旋锁
  1. ASE15.7 ESD#1之前的版本当更新内存计数结构时使用自旋锁
    原因是创建另外一个自旋锁的竞争
    3. 高竞争比的原因包括:
    大量使用动态SQL
    过程缓存太小
  2. 可能的解决措施和rproccache_spin 一样
  • Lock Manager spinlocks(fglockspins,addrlockspins,tablockspins)

    1. 这些自旋锁用来保护 lock manager hashtables
    2. 如果lock HWMs 设置的太高,意为着更多的锁和竞争
    3. 达到目标的主要方式是调节配置
      lock spinlock ratio
      lock address spinlock ratio
      lock table spinlock ratio
      lock hashtable size

谨记

  • 抵制因CPU高而添加更多引擎的诱惑
    如果CPU高是因为自旋锁竞争引起的,添加更多的CPU只会使事情更糟。
    添加更多的"spinner"只会简单的增加每个spid 获取自旋锁的时间,甚至更慢。
posted @ 2017-10-09 13:45  wangzhen3798  阅读(919)  评论(0编辑  收藏  举报