InnoDB
互斥锁和
读写锁通常保留很短的时间间隔。在多核系统上,线程在休眠前持续检查是否可以在一段时间内获取互斥锁或读写锁会更高效。如果在此期间互斥锁或读写锁可用,则线程可以在同一时间片中立即继续。然而,多个线程对共享对象(如互斥锁或读写锁)的过于频繁的轮询会导致“缓存乒乓”,从而导致处理器使彼此缓存的部分无效。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 指令数。设置为 5 会产生一
innodb_spin_wait_delay
组五个可能的值
{0,50,100,150,200}
,其中 200 是 PAUSE 指令的最大数量,依此类推。这样,该
innodb_spin_wait_delay
设置控制自旋锁轮询之间的最大延迟。
在所有处理器内核共享高速缓存内存的系统上,您可以通过设置来减少最大延迟或完全禁用繁忙循环
innodb_spin_wait_delay=0
。在具有多个处理器芯片的系统上,缓存失效的影响可能更为显着,您可能会增加最大延迟。
在100MHz奔腾时代,一个
innodb_spin_wait_delay
单位被校准为相当于一微秒。那个时间等效性不成立,但 PAUSE 指令持续时间相对于其他 CPU 指令在处理器周期方面保持相当恒定,直到引入具有相对较长的 PAUSE 指令的 Skylake 一代处理器。该
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
语句修改。在运行时修改变量需要足够的权限来设置全局系统变量。请参阅
第 5.1.9.1 节,“系统变量权限”。