配置自旋锁定轮询
InnoDB
互斥锁和 rw锁通常保留较短的时间间隔。在多核系统上,线程在睡眠之前的一段时间内连续检查它是否可以获取互斥或rw-lock可能会更有效率。如果在此期间互斥锁或rw-lock可用,则线程可以在同一时间片中立即继续。但是,通过多个线程对共享对象(例如互斥锁或rw-lock)进行太频繁的轮询会导致“高速缓存乒乓”,这导致处理器使彼此的部分高速缓存无效。InnoDB
通过强制轮询之间的随机延迟使轮询活动不同步,可以最大程度地减少此问题。随机延迟被实现为旋转等待循环。
旋转等待循环的持续时间取决于循环中发生的PAUSE指令的数量。通过随机选择一个从0到不包括该innodb_spin_wait_delay
值的整数,然后将该值乘以50 来生成该数字。(乘数50在MySQL 8.0.16之前是硬编码的,此后可配置。)例如,从以下范围中随机选择一个整数,innodb_spin_wait_delay
设置为6:
{0,1,2,3,4,5}
所选整数乘以50,得到六个可能的PAUSE指令值之一:
{0,50,100,150,200,250}
对于该组值,250是旋转等待循环中可能出现的最大PAUSE指令数。一个innodb_spin_wait_delay
的5个结果中的一组的五个可能值的设定{0,50,100,150,200}
,其中,200是暂停指令的最大数量,等等。这样,该innodb_spin_wait_delay
设置可控制自旋锁定轮询之间的最大延迟。
在所有处理器核心共享快速缓存的系统上,可以通过设置来减少最大延迟或完全禁用繁忙循环innodb_spin_wait_delay=0
。在具有多个处理器芯片的系统上,缓存无效化的影响可能更大,并且可能会增加最大延迟。
在100MHz奔腾时代,innodb_spin_wait_delay
单位被校准为相当于一微秒。那个时间上的等价性不成立,但是相对于其他CPU指令,PAUSE指令的持续时间在处理器周期方面保持相当恒定,直到推出Skylake系列处理器(具有相对较长的PAUSE指令)为止。该innodb_spin_wait_pause_multiplier
变量在MySQL 8.0.16中引入,以提供一种解决PAUSE指令持续时间差异的方法。
该innodb_spin_wait_pause_multiplier
变量控制PAUSE指令值的大小。例如,假设innodb_spin_wait_delay
设置为6,则将该innodb_spin_wait_pause_multiplier
值从50(默认值和先前的硬编码值)减小到5,会生成一组较小的PAUSE指令值:
{0,5,10,15,20,25}
增加或减少PAUSE指令值的能力允许InnoDB
对不同的处理器体系结构进行微调。例如,较小的PAUSE指令值将适合于具有相对较长的PAUSE指令的处理器体系结构。
在innodb_spin_wait_delay
和innodb_spin_wait_pause_multiplier
变量是动态的。它们可以在MySQL选项文件中指定,也可以在运行时使用一条SET GLOBAL
语句进行修改。在运行时修改变量需要足够的特权来设置全局系统变量。请参见“系统变量特权”。