<span style="font-size:14px;"> </span><span style="font-size:14px;">最近一次故障,由于开发同学大量的slow sql导致数据库响应缓慢,通过ptstack发现大量的thread都处在</span><span style="font-size:14px;">os_thread_sleep状态,<br />
所以打算从底层分析到底为何会有如此多的sleep。</span><br />
<span style="font-size:14px;"><br />
下面罗列一下当时详细的堆栈情况:</span><br />
<div>
<div class="codeheads">
<p>
点击(<span style="cursor:pointer;color:red;" .="code_hide(‘code353‘)">此处</span>)折叠或打开
</p>
</div>
<div id="code353" class="codeText">
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css">
<li>
<span style="color:#000000;">Thread 273 <span style="color:#0000CC;">(</span>Thread 0x2acecc040700 <span style="color:#0000CC;">(</span>LWP 182856<span style="color:#0000CC;">)</span><span style="color:#0000CC;">)</span><span style="color:#0000CC;">:</span><br />
</span>
</li>
<li>
#0 0x00000033b9ce1373 <span style="color:#0000FF;">in</span> <span style="color:#0000FF;">select</span> <span style="color:#0000CC;">(</span><span style="color:#0000CC;">)</span> from <span style="color:#0000CC;">/</span>lib64<span style="color:#0000CC;">/</span>libc<span style="color:#0000CC;">.</span>so<span style="color:#0000CC;">.</span>6<br />
</li>
<li>
#1 0x000000000096d1af <span style="color:#0000FF;">in</span> <span style="color:#E53333;"><strong>os_thread_sleep</strong></span><span style="color:#0000CC;">(</span>unsigned long<span style="color:#0000CC;">)</span> <span style="color:#0000CC;">(</span><span style="color:#0000CC;">)</span><br />
</li>
<li>
#2 0x00000000009cd334 <span style="color:#0000FF;">in</span> <strong><span style="color:#E53333;">srv_conc_enter_innodb</span></strong><span style="color:#0000CC;">(</span>trx_t<span style="color:#0000CC;">*</span><span style="color:#0000CC;">)</span> <span style="color:#0000CC;">(</span><span style="color:#0000CC;">)</span><br />
</li>
<li>
#3 0x0000000000917028 <span style="color:#0000FF;">in</span> ha_innobase<span style="color:#0000CC;">:</span><span style="color:#0000CC;">:</span>write_row<span style="color:#0000CC;">(</span>unsigned char<span style="color:#0000CC;">*</span><span style="color:#0000CC;">)</span> <span style="color:#0000CC;">(</span><span style="color:#0000CC;">)</span><br />
</li>
<li>
#4 0x00000000005c5c3d <span style="color:#0000FF;">in</span> handler<span style="color:#0000CC;">:</span><span style="color:#0000CC;">:</span>ha_write_row<span style="color:#0000CC;">(</span>unsigned char<span style="color:#0000CC;">*</span><span style="color:#0000CC;">)</span> <span style="color:#0000CC;">(</span><span style="color:#0000CC;">)</span><br />
</li>
<li>
#5 0x00000000006e4245 <span style="color:#0000FF;">in</span> write_record<span style="color:#0000CC;">(</span>THD<span style="color:#0000CC;">*</span><span style="color:#0000CC;">,</span> TABLE<span style="color:#0000CC;">*</span><span style="color:#0000CC;">,</span> COPY_INFO<span style="color:#0000CC;">*</span><span style="color:#0000CC;">,</span> COPY_INFO<span style="color:#0000CC;">*</span><span style="color:#0000CC;">)</span> <span style="color:#0000CC;">(</span><span style="color:#0000CC;">)</span><br />
</li>
<li>
#6 0x00000000006e9cc9 <span style="color:#0000FF;">in</span> mysql_insert<span style="color:#0000CC;">(</span>THD<span style="color:#0000CC;">*</span><span style="color:#0000CC;">,</span> TABLE_LIST<span style="color:#0000CC;">*</span><span style="color:#0000CC;">,</span> List<span style="color:#0000CC;"><</span>Item<span style="color:#0000CC;">></span><span style="color:#0000CC;">&</span><span style="color:#0000CC;">,</span> List<span style="color:#0000CC;"><</span>List<span style="color:#0000CC;"><</span>Item<span style="color:#0000CC;">></span> <span style="color:#0000CC;">></span><span style="color:#0000CC;">&</span><span style="color:#0000CC;">,</span> List<span style="color:#0000CC;"><</span>Item<span style="color:#0000CC;">></span><span style="color:#0000CC;">&</span><span style="color:#0000CC;">,</span> List<span style="color:#0000CC;"><</span>Item<span style="color:#0000CC;">></span><span style="color:#0000CC;">&</span><span style="color:#0000CC;">,</span> enum_duplicates<span style="color:#0000CC;">,</span> bool<span style="color:#0000CC;">)</span> <span style="color:#0000CC;">(</span><span style="color:#0000CC;">)</span><br />
</li>
<li>
#7 0x00000000006fcb5c <span style="color:#0000FF;">in</span> mysql_execute_command<span style="color:#0000CC;">(</span>THD<span style="color:#0000CC;">*</span><span style="color:#0000CC;">)</span> <span style="color:#0000CC;">(</span><span style="color:#0000CC;">)</span><br />
</li>
<li>
#8 0x0000000000701f38 <span style="color:#0000FF;">in</span> mysql_parse<span style="color:#0000CC;">(</span>THD<span style="color:#0000CC;">*</span><span style="color:#0000CC;">,</span> char<span style="color:#0000CC;">*</span><span style="color:#0000CC;">,</span> unsigned <span style="color:#FF0000;">int</span><span style="color:#0000CC;">,</span> Parser_state<span style="color:#0000CC;">*</span><span style="color:#0000CC;">)</span> <span style="color:#0000CC;">(</span><span style="color:#0000CC;">)</span><br />
</li>
<li>
#9 0x000000000070375c <span style="color:#0000FF;">in</span> dispatch_command<span style="color:#0000CC;">(</span>enum_server_command<span style="color:#0000CC;">,</span> THD<span style="color:#0000CC;">*</span><span style="color:#0000CC;">,</span> char<span style="color:#0000CC;">*</span><span style="color:#0000CC;">,</span> unsigned <span style="color:#FF0000;">int</span><span style="color:#0000CC;">)</span> <span style="color:#0000CC;">(</span><span style="color:#0000CC;">)</span><br />
</li>
<li>
#10 0x000000000078e158 <span style="color:#0000FF;">in</span> threadpool_process_request<span style="color:#0000CC;">(</span>THD<span style="color:#0000CC;">*</span><span style="color:#0000CC;">)</span> <span style="color:#0000CC;">(</span><span style="color:#0000CC;">)</span><br />
</li>
<li>
#11 0x000000000078f12d <span style="color:#0000FF;">in</span> worker_main<span style="color:#0000CC;">(</span>void<span style="color:#0000CC;">*</span><span style="color:#0000CC;">)</span> <span style="color:#0000CC;">(</span><span style="color:#0000CC;">)</span><br />
</li>
<li>
#12 0x0000000000b03a83 <span style="color:#0000FF;">in</span> pfs_spawn_thread <span style="color:#0000CC;">(</span><span style="color:#0000CC;">)</span><br />
</li>
<li>
#13 0x00000033ba0079d1 <span style="color:#0000FF;">in</span> start_thread <span style="color:#0000CC;">(</span><span style="color:#0000CC;">)</span> from <span style="color:#0000CC;">/</span>lib64<span style="color:#0000CC;">/</span>libpthread<span style="color:#0000CC;">.</span>so<span style="color:#0000CC;">.</span>0<br />
</li>
<li>
#14 0x00000033b9ce88fd <span style="color:#0000FF;">in</span> clone <span style="color:#0000CC;">(</span><span style="color:#0000CC;">)</span> from <span style="color:#0000CC;">/</span>lib64<span style="color:#0000CC;">/</span>libc<span style="color:#0000CC;">.</span>so<span style="color:#0000CC;">.</span>6
</li>
</ol>
</div>
</div>
<span style="font-size:14px;">通过堆栈,我们很清晰的看到,函数通过srv_conc_enter_innodb调用os_thread_sleep ,进而进入sleep 状态。<br />
</span><span style="font-size:14px;">接下来,我们略过其他的冗长的函数,直接从srv_conc_enter_innodb看看此时mysql到底在做什么 。<br />
</span><br />
<span style="font-size:14px;line-height:21px;white-space:normal;"><strong>首先贴一下处理该部分逻辑的代码段,关于该代码段的具体含义,后面会给出。</strong></span><br />
<div>
<div class="codeheads">
<p>
点击(<span style="cursor:pointer;color:red;" .="code_hide(‘code88‘)">此处</span>)折叠或打开
</p>
</div>
<div id="code88" class="codeText">
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css">
<li>
<span style="color:#000000;"><span style="color:#0000CC;">/</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">/</span><span style="color:#0000CC;">/</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">*</span><br />
</span>
</li>
<li>
Handle the scheduling of a user thread that wants <span style="color:#0000FF;">to</span> enter InnoDB<span style="color:#0000CC;">.</span> Setting<br />
</li>
<li>
srv_adaptive_max_sleep_delay <span style="color:#0000CC;">></span> 0 switches the adaptive sleep calibration <span style="color:#0000FF;">to</span><br />
</li>
<li>
<span style="color:#0000FF;">ON</span><span style="color:#0000CC;">.</span> When <span style="color:#0000FF;">set</span><span style="color:#0000CC;">,</span> we want <span style="color:#0000FF;">to</span> wait <span style="color:#0000FF;">in</span> the queue <span style="color:#0000FF;">for</span> as little <span style="color:#FF0000;">time</span> as possible<span style="color:#0000CC;">.</span><br />
</li>
<li>
However<span style="color:#0000CC;">,</span> very short waits will result <span style="color:#0000FF;">in</span> a lot of context switches <span style="color:#0000FF;">and</span> that<br />
</li>
<li>
<span style="color:#0000FF;">is</span> also <span style="color:#0000FF;">not</span> desirable<span style="color:#0000CC;">.</span> When threads need <span style="color:#0000FF;">to</span> sleep multiple times we increment<br />
</li>
<li>
os_thread_sleep_delay by one<span style="color:#0000CC;">.</span> When we see threads getting a slot without<br />
</li>
<li>
waiting <span style="color:#0000FF;">and</span> there are no other threads waiting <span style="color:#0000FF;">in</span> the queue<span style="color:#0000CC;">,</span> we try <span style="color:#0000FF;">and</span> reduce<br />
</li>
<li>
the wait as much as we can<span style="color:#0000CC;">.</span> Currently we reduce it by half <span style="color:#0000FF;">each</span> <span style="color:#FF0000;">time</span><span style="color:#0000CC;">.</span> <span style="color:#0000FF;">If</span> the<br />
</li>
<li>
thread only had <span style="color:#0000FF;">to</span> wait <span style="color:#0000FF;">for</span> one turn before it was able <span style="color:#0000FF;">to</span> enter InnoDB we<br />
</li>
<li>
decrement it by one<span style="color:#0000CC;">.</span> This <span style="color:#0000FF;">is</span> <span style="color:#0000FF;">to</span> try <span style="color:#0000FF;">and</span> keep the sleep <span style="color:#FF0000;">time</span> stable around the<br />
</li>
<li>
<span style="color:#FF00FF;">"optimum"</span> sleep <span style="color:#FF0000;">time</span><span style="color:#0000CC;">.</span> <span style="color:#0000CC;">*</span><span style="color:#0000CC;">/</span><br />
</li>
<li>
<br />
</li>
<li>
static void <br />
</li>
<li>
srv_conc_enter_innodb_with_atomics<span style="color:#0000CC;">(</span><br />
</li>
<li>
<span style="color:#0000CC;">/</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">/</span><br />
</li>
<li>
trx_t<span style="color:#0000CC;">*</span> trx<span style="color:#0000CC;">)</span> <span style="color:#0000CC;">/</span><span style="color:#0000CC;">*</span><span style="color:#0000CC;">!</span><span style="color:#0000CC;"><</span> <span style="color:#0000FF;">in</span><span style="color:#0000CC;">/</span>out<span style="color:#0000CC;">:</span> transaction that wants<br />
</li>
<li>
<span style="color:#0000FF;">to</span> enter InnoDB <span style="color:#0000CC;">*</span><span style="color:#0000CC;">/</span><br />
</li>
<li>
<span style="color:#0000CC;">{</span><br />
</li>
<li>
ulint n_sleeps <span style="color:#0000CC;">=</span> 0<span style="color:#0000CC;">;</span><br />
</li>
<li>
ibool notified_mysql <span style="color:#0000CC;">=</span> <span style="color:#0000FF;">FALSE</span><span style="color:#0000CC;">;</span><br />
</li>
<li>
ut_a<span style="color:#0000CC;">(</span><span style="color:#0000CC;">!</span>trx<span style="color:#0000CC;">-</span><span style="color:#0000CC;">></span>declared_to_be_inside_innodb<span style="color:#0000CC;">)</span><span style="color:#0000CC;">;</span><br />
</li>
<li>
<span style="color:#0000FF;">for</span> <span style="color:#0000CC;">(</span><span style="color:#0000CC;">;</span><span style="color:#0000CC;">;</span><span style="color:#0000CC;">)</span> <span style="color:#0000CC;">{</span><br />
</li>
<li>
ulint sleep_in_us<span style="color:#0000CC;">;</span><br />
</li>
<li>
<span style="color:#0000FF;">if</span> <span style="color:#0000CC;">(</span>srv_conc<span style="color:#0000CC;">.</span>n_active <span style="color:#0000CC;"><</span> <span style="color:#0000CC;">(</span>lint<span style="color:#0000CC;">)</span> srv_thread_concurrency<span style="color:#0000CC;">)</span> <span style="color:#0000CC;">{</span><br />
</li>
<li>
ulint n_active<span style="color:#0000CC;">;</span><br />
</li>
<li>
<br />
</li>
<li>
<span style="color:#0000CC;">/</span><span style="color:#0000CC;">*</span> Check <span style="color:#0000FF;">if</span> there are any free tickets<span style="color:#0000CC;">.</span> <span style="color:#0000CC;">*</span><span style="color:#0000CC;">/</span><br />
</li>
<li>
n_active <span style="color:#0000CC;">=</span> os_atomic_increment_lint<span style="color:#0000CC;">(</span><br />
</li>
<li>
<span style="color:#0000CC;">&</span>srv_conc<span style="color:#0000CC;">.</span>n_active<span style="color:#0000CC;">,</span> 1<span style="color:#0000CC;">)</span><span style="color:#0000CC;">;</span><br />
</li>
<li>
<br />
</li>
<li>
<span style="color:#0000FF;">if</span> <span style="color:#0000CC;">(</span>n_active <span style="color:#0000CC;"><</span><span style="color:#0000CC;">=</span> srv_thread_concurrency<span style="color:#0000CC;">)</span> <span style="color:#0000CC;">{</span><br />
</li>
<li>
<br />
</li>
<li>
srv_enter_innodb_with_tickets<span style="color:#0000CC;">(</span>trx<span style="color:#0000CC;">)</span><span style="color:#0000CC;">;</span><br />
</li>
<li>
<br />
</li>
<li>
<span style="color:#0000FF;">if</span> <span style="color:#0000CC;">(</span>notified_mysql<span style="color:#0000CC;">)</span> <span style="color:#0000CC;">{</span><br />
</li>
<li>
<span style="color:#0000CC;">(</span>void<span style="color:#0000CC;">)</span> os_atomic_decrement_lint<span style="color:#0000CC;">(</span><br />
</li>
<li>
<span style="color:#0000CC;">&</span>srv_conc<span style="color:#0000CC;">.</span>n_waiting<span style="color:#0000CC;">,</span> 1<span style="color:#0000CC;">)</span><span style="color:#0000CC;">;</span><br />
</li>
<li>
thd_wait_end<span style="color:#0000CC;">(</span>trx<span style="color:#0000CC;">-</span><span style="color:#0000CC;">></span>mysql_thd<span style="color:#0000CC;">)</span><span style="color:#0000CC;">;</span><br />
</li>
<li>
<span style="color:#0000CC;">}</span><br />
</li>
<li>
<br />
</li>
<li>
<span style="color:#0000FF;">if</span> <span style="color:#0000CC;">(</span>srv_adaptive_max_sleep_delay <span style="color:#0000CC;">></span> 0<span style="color:#0000CC;">)</span> <span style="color:#0000CC;">{</span><br />
</li>
<li>
<span style="color:#0000FF;">if</span> <span style="color:#0000CC;">(</span>srv_thread_sleep_delay <span style="color:#0000CC;">></span> 20<br />
</li>
<li>
<span style="color:#0000CC;">&</span><span style="color:#0000CC;">&</span> n_sleeps <span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span> 1<span style="color:#0000CC;">)</span> <span style="color:#0000CC;">{</span><br />
</li>
<li>
<br />
</li>
<li>
<span style="color:#0000CC;">-</span><span style="color:#0000CC;">-</span>srv_thread_sleep_delay<span style="color:#0000CC;">;</span><br />
</li>
<li>
<span style="color:#0000CC;">}</span><br />
</li>
<li>
<br />
</li>
<li>
<span style="color:#0000FF;">if</span> <span style="color:#0000CC;">(</span>srv_conc<span style="color:#0000CC;">.</span>n_waiting <span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span> 0<span style="color:#0000CC;">)</span> <span style="color:#0000CC;">{</span><br />
</li>
<li>
srv_thread_sleep_delay <span style="color:#0000CC;">></span><span style="color:#0000CC;">></span><span style="color:#0000CC;">=</span> 1<span style="color:#0000CC;">;</span><br />
</li>
<li>
<span style="color:#0000CC;">}</span><br />
</li>
<li>
<span style="color:#0000CC;">}</span><br />
</li>
<li>
return<span style="color:#0000CC;">;</span><br />
</li>
<li>
<span style="color:#0000CC;">}</span><br />
</li>
<li>
<br />
</li>
<li>
<span style="color:#0000CC;">/</span><span style="color:#0000CC;">*</span> Since there were no free seats<span style="color:#0000CC;">,</span> we relinquish the overbooked ticket<span style="color:#0000CC;">.</span> <span style="color:#0000CC;">*</span><span style="color:#0000CC;">/</span><br />
</li>
<li>
<br />
</li>
<li>
<span style="color:#0000CC;">(</span>void<span style="color:#0000CC;">)</span> os_atomic_decrement_lint<span style="color:#0000CC;">(</span><span style="color:#0000CC;">&</span>srv_conc<span style="color:#0000CC;">.</span>n_active<span style="color:#0000CC;">,</span> 1<span style="color:#0000CC;">)</span><span style="color:#0000CC;">;</span><br />
</li>
<li>
<span style="color:#0000CC;">}</span><br />
</li>
<li>
<span style="color:#0000FF;">if</span> <span style="color:#0000CC;">(</span><span style="color:#0000CC;">!</span>notified_mysql<span style="color:#0000CC;">)</span> <span style="color:#0000CC;">{</span><br />
</li>
<li>
<span style="color:#0000CC;">(</span>void<span style="color:#0000CC;">)</span> os_atomic_increment_lint<span style="color:#0000CC;">(</span><span style="color:#0000CC;">&</span>srv_conc<span style="color:#0000CC;">.</span>n_waiting<span style="color:#0000CC;">,</span> 1<span style="color:#0000CC;">)</span><span style="color:#0000CC;">;</span><br />
</li>
<li>
<br />
</li>
<li>
<span style="color:#0000CC;">/</span><span style="color:#0000CC;">*</span> Release possible search system latch this thread has <span style="color:#0000CC;">*</span><span style="color:#0000CC;">/</span><br />
</li>
<li>
<span style="color:#0000FF;">if</span> <span style="color:#0000CC;">(</span>trx<span style="color:#0000CC;">-</span><span style="color:#0000CC;">></span>has_search_latch<span style="color:#0000CC;">)</span> <span style="color:#0000CC;">{</span><br />
</li>
<li>
trx_search_latch_release_if_reserved<span style="color:#0000CC;">(</span>trx<span style="color:#0000CC;">)</span><span style="color:#0000CC;">;</span><br />
</li>
<li>
<span style="color:#0000CC;">}</span><br />
</li>
<li>
<br />
</li>
<li>
thd_wait_begin<span style="color:#0000CC;">(</span>trx<span style="color:#0000CC;">-</span><span style="color:#0000CC;">></span>mysql_thd<span style="color:#0000CC;">,</span> THD_WAIT_USER_LOCK<span style="color:#0000CC;">)</span><span style="color:#0000CC;">;</span><br />
</li>
<li>
notified_mysql <span style="color:#0000CC;">=</span> <span style="color:#0000FF;">TRUE</span><span style="color:#0000CC;">;</span><br />
</li>
<li>
<span style="color:#0000CC;">}</span><br />
</li>
<li>
<br />
</li>
<li>
trx<span style="color:#0000CC;">-</span><span style="color:#0000CC;">></span>op_info <span style="color:#0000CC;">=</span> <span style="color:#FF00FF;">"sleeping before entering InnoDB"</span><span style="color:#0000CC;">;</span><br />
</li>
<li>
sleep_in_us <span style="color:#0000CC;">=</span> srv_thread_sleep_delay<span style="color:#0000CC;">;</span><br />
</li>
<li>
<br />
</li>
<li>
<span style="color:#0000CC;">/</span><span style="color:#0000CC;">*</span> Guard against overflow when adaptive sleep delay <span style="color:#0000FF;">is</span> <span style="color:#0000FF;">on</span><span style="color:#0000CC;">.</span> <span style="color:#0000CC;">*</span><span style="color:#0000CC;">/</span><br />
</li>
<li>
<span style="color:#0000FF;">if</span> <span style="color:#0000CC;">(</span>srv_adaptive_max_sleep_delay <span style="color:#0000CC;">></span> 0<br />
</li>
<li>
<span style="color:#0000CC;">&</span><span style="color:#0000CC;">&</span> sleep_in_us <span style="color:#0000CC;">></span> srv_adaptive_max_sleep_delay<span style="color:#0000CC;">)</span> <span style="color:#0000CC;">{</span><br />
</li>
<li>
sleep_in_us <span style="color:#0000CC;">=</span> srv_adaptive_max_sleep_delay<span style="color:#0000CC;">;</span><br />
</li>
<li>
srv_thread_sleep_delay <span style="color:#0000CC;">=</span> sleep_in_us<span style="color:#0000CC;">;</span><br />
</li>
<li>
<span style="color:#0000CC;">}</span><br />
</li>
<li>
os_thread_sleep<span style="color:#0000CC;">(</span>sleep_in_us<span style="color:#0000CC;">)</span><span style="color:#0000CC;">;</span><br />
</li>
<li>
trx<span style="color:#0000CC;">-</span><span style="color:#0000CC;">></span>innodb_que_wait_timer <span style="color:#0000CC;">+</span><span style="color:#0000CC;">=</span> sleep_in_us<span style="color:#0000CC;">;</span><br />
</li>
<li>
trx<span style="color:#0000CC;">-</span><span style="color:#0000CC;">></span>op_info <span style="color:#0000CC;">=</span> <span style="color:#FF00FF;">""</span><span style="color:#0000CC;">;</span><br />
</li>
<li>
<span style="color:#0000CC;">+</span><span style="color:#0000CC;">+</span>n_sleeps<span style="color:#0000CC;">;</span><br />
</li>
<li>
<br />
</li>
<li>
<span style="color:#0000FF;">if</span> <span style="color:#0000CC;">(</span>srv_adaptive_max_sleep_delay <span style="color:#0000CC;">></span> 0 <span style="color:#0000CC;">&</span><span style="color:#0000CC;">&</span> n_sleeps <span style="color:#0000CC;">></span> 1<span style="color:#0000CC;">)</span> <span style="color:#0000CC;">{</span><br />
</li>
<li>
<span style="color:#0000CC;">+</span><span style="color:#0000CC;">+</span>srv_thread_sleep_delay<span style="color:#0000CC;">;</span><br />
</li>
<li>
<span style="color:#0000CC;">}</span><br />
</li>
<li>
<span style="color:#0000CC;">}</span><br />
</li>
<li>
<span style="color:#0000CC;">}</span>
</li>
</ol>
</div>
</div>
<span style="font-size:14px;">从代码,我们来看看两部分内容。</span><br />
<span style="font-size:14px;">一.<strong><span style="color:#009900;">如果目前thread running的个数,已经超过了innodb_thread_concurrency,该thread会如何处置呢 ?</span></strong></span><br />
<span style="font-size:14px;">我们来看看重点部分:</span><br />
<div>
<div class="codeheads">
<p>
点击(<span style="cursor:pointer;color:red;" .="code_hide(‘code50‘)">此处</span>)折叠或打开
</p>
</div>
<div id="code50" class="codeText">
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css">
<li>
<span style="color:#000000;"> trx<span style="color:#0000CC;">-</span><span style="color:#0000CC;">></span>op_info <span style="color:#0000CC;">=</span> <span style="color:#FF00FF;">"sleeping before entering InnoDB"</span><span style="color:#0000CC;">;</span><br />
</span>
</li>
<li>
sleep_in_us <span style="color:#0000CC;">=</span> srv_thread_sleep_delay<span style="color:#0000CC;">;</span><br />
</li>
<li>
<span style="color:#0000CC;">/</span><span style="color:#0000CC;">*</span> Guard against overflow when adaptive sleep delay <span style="color:#0000FF;">is</span> <span style="color:#0000FF;">on</span><span style="color:#0000CC;">.</span> <span style="color:#0000CC;">*</span><span style="color:#0000CC;">/</span><br />
</li>
<li>
<br />
</li>
<li>
<span style="color:#0000FF;">if</span> <span style="color:#0000CC;">(</span>srv_adaptive_max_sleep_delay <span style="color:#0000CC;">></span> 0<br />
</li>
<li>
<span style="color:#0000CC;">&</span><span style="color:#0000CC;">&</span> sleep_in_us <span style="color:#0000CC;">></span> srv_adaptive_max_sleep_delay<span style="color:#0000CC;">)</span> <span style="color:#0000CC;">{</span><br />
</li>
<li>
sleep_in_us <span style="color:#0000CC;">=</span> srv_adaptive_max_sleep_delay<span style="color:#0000CC;">;</span><br />
</li>
<li>
srv_thread_sleep_delay <span style="color:#0000CC;">=</span> sleep_in_us<span style="color:#0000CC;">;</span><br />
</li>
<li>
<span style="color:#0000CC;">}</span><br />
</li>
<li>
os_thread_sleep<span style="color:#0000CC;">(</span>sleep_in_us<span style="color:#0000CC;">)</span><span style="color:#0000CC;">;</span><br />
</li>
<li>
trx<span style="color:#0000CC;">-</span><span style="color:#0000CC;">></span>innodb_que_wait_timer <span style="color:#0000CC;">+</span><span style="color:#0000CC;">=</span> sleep_in_us<span style="color:#0000CC;">;</span><br />
</li>
<li>
trx<span style="color:#0000CC;">-</span><span style="color:#0000CC;">></span>op_info <span style="color:#0000CC;">=</span> <span style="color:#FF00FF;">""</span><span style="color:#0000CC;">;</span><br />
</li>
<li>
<span style="color:#0000CC;">+</span><span style="color:#0000CC;">+</span>n_sleeps<span style="color:#0000CC;">;</span><br />
</li>
<li>
<span style="color:#0000FF;">if</span> <span style="color:#0000CC;">(</span>srv_adaptive_max_sleep_delay <span style="color:#0000CC;">></span> 0 <span style="color:#0000CC;">&</span><span style="color:#0000CC;">&</span> n_sleeps <span style="color:#0000CC;">></span> 1<span style="color:#0000CC;">)</span> <span style="color:#0000CC;">{</span><br />
</li>
<li>
<span style="color:#0000CC;">+</span><span style="color:#0000CC;">+</span>srv_thread_sleep_delay<span style="color:#0000CC;">;</span><br />
</li>
<li>
<span style="color:#0000CC;">}</span>
</li>
</ol>
</div>
</div>
<br />
<br />
<span style="font-size:14px;color:#E53333;"><strong> 1.设置该thread需要sleep的时间为srv_thread_sleep_delay(默认10ms).</strong></span><br />
<span style="font-size:14px;"> <span style="color:#E53333;"><strong>2.判断需要sleep的时间是否大于srv_adaptive_max_sleep_delay(默认150ms),如果大于该值,调整为该值.(避免sleep 时间过久,性能受到影响).</strong></span></span><br />
<span style="font-size:14px;"> <span style="color:#E53333;"><strong>3.开始sleep,如果该线程已经sleep过一次了,则下次sleep的时间在上次基础上加1(说明系统比较繁忙,该thread多次醒来都无法得到处理,不如继续让它多睡一会儿).</strong></span></span><br />
<span style="font-size:14px;"> </span><br />
<span style="font-size:14px;"> 二:<strong><span style="color:#009900;">如果thread running的个数,还未超过innodb_thread_concurrency,也就是说队列尚未满,此时thread可以进入innodb,从而得到及时的处理。</span></strong></span><br />
<span style="font-size:14px;"> 此时,我们看看,mysql是如何处理这部分逻辑:</span><span style="font-size:14px;"> <br />
<div>
<div class="codeheads">
<p>
点击(<span style="cursor:pointer;color:red;" .="code_hide(‘code848‘)">此处</span>)折叠或打开
</p>
</div>
<div id="code848" class="codeText">
<ol style="margin:0 1px 0 0px;padding-left:40px;" start="1" class="dp-css">
<li>
<span style="color:#000000;"><span style="color:#0000FF;">if</span> <span style="color:#0000CC;">(</span>srv_conc<span style="color:#0000CC;">.</span>n_active <span style="color:#0000CC;"><</span> <span style="color:#0000CC;">(</span>lint<span style="color:#0000CC;">)</span> srv_thread_concurrency<span style="color:#0000CC;">)</span> <span style="color:#0000CC;">{</span><br />
</span>
</li>
<li>
ulint n_active<span style="color:#0000CC;">;</span><br />
</li>
<li>
<span style="color:#0000CC;">/</span><span style="color:#0000CC;">*</span> Check <span style="color:#0000FF;">if</span> there are any free tickets<span style="color:#0000CC;">.</span> <span style="color:#0000CC;">*</span><span style="color:#0000CC;">/</span><br />
</li>
<li>
n_active <span style="color:#0000CC;">=</span> os_atomic_increment_lint<span style="color:#0000CC;">(</span> <span style="color:#0000CC;">&</span>srv_conc<span style="color:#0000CC;">.</span>n_active<span style="color:#0000CC;">,</span> 1<span style="color:#0000CC;">)</span><span style="color:#0000CC;">;</span><br />
</li>
<li>
<span style="color:#0000FF;">if</span> <span style="color:#0000CC;">(</span>n_active <span style="color:#0000CC;"><</span><span style="color:#0000CC;">=</span> srv_thread_concurrency<span style="color:#0000CC;">)</span> <span style="color:#0000CC;">{</span><br />
</li>
<li>
srv_enter_innodb_with_tickets<span style="color:#0000CC;">(</span>trx<span style="color:#0000CC;">)</span><span style="color:#0000CC;">;</span><br />
</li>
<li>
<span style="color:#0000FF;">if</span> <span style="color:#0000CC;">(</span>notified_mysql<span style="color:#0000CC;">)</span> <span style="color:#0000CC;">{</span><br />
</li>
<li>
<span style="color:#0000CC;">(</span>void<span style="color:#0000CC;">)</span> os_atomic_decrement_lint<span style="color:#0000CC;">(</span><span style="color:#0000CC;">&</span>srv_conc<span style="color:#0000CC;">.</span>n_waiting<span style="color:#0000CC;">,</span> 1<span style="color:#0000CC;">)</span><span style="color:#0000CC;">;</span><br />
</li>
<li>
thd_wait_end<span style="color:#0000CC;">(</span>trx<span style="color:#0000CC;">-</span><span style="color:#0000CC;">></span>mysql_thd<span style="color:#0000CC;">)</span><span style="color:#0000CC;">;</span><br />
</li>
<li>
<span style="color:#0000CC;">}</span><br />
</li>
<li>
<span style="color:#0000FF;">if</span> <span style="color:#0000CC;">(</span>srv_adaptive_max_sleep_delay <span style="color:#0000CC;">></span> 0<span style="color:#0000CC;">)</span> <span style="color:#0000CC;">{</span><br />
</li>
<li>
<span style="color:#0000FF;">if</span> <span style="color:#0000CC;">(</span>srv_thread_sleep_delay <span style="color:#0000CC;">></span> 20<br />
</li>
<li>
<span style="color:#0000CC;">&</span><span style="color:#0000CC;">&</span> n_sleeps <span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span> 1<span style="color:#0000CC;">)</span> <span style="color:#0000CC;">{</span><br />
</li>
<li>
<span style="color:#0000CC;">-</span><span style="color:#0000CC;">-</span>srv_thread_sleep_delay<span style="color:#0000CC;">;</span><br />
</li>
<li>
<span style="color:#0000CC;">}</span><br />
</li>
<li>
<span style="color:#0000FF;">if</span> <span style="color:#0000CC;">(</span>srv_conc<span style="color:#0000CC;">.</span>n_waiting <span style="color:#0000CC;">=</span><span style="color:#0000CC;">=</span> 0<span style="color:#0000CC;">)</span> <span style="color:#0000CC;">{</span><br />
</li>
<li>
srv_thread_sleep_delay <span style="color:#0000CC;">></span><span style="color:#0000CC;">></span><span style="color:#0000CC;">=</span> 1<span style="color:#0000CC;">;</span><br />
</li>
<li>
<span style="color:#0000CC;">}</span><br />
</li>
<li>
<span style="color:#0000CC;">}</span><br />
</li>
<li>
return<span style="color:#0000CC;">;</span><br />
</li>
<li>
<span style="color:#0000CC;">}</span><br />
</li>
<li>
<br />
</li>
<li>
<span style="color:#0000CC;">/</span><span style="color:#0000CC;">*</span> Since there were no free seats<span style="color:#0000CC;">,</span> we relinquish<br />
</li>
<li>
the overbooked ticket<span style="color:#0000CC;">.</span> <span style="color:#0000CC;">*</span><span style="color:#0000CC;">/</span><br />
</li>
<li>
<span style="color:#0000CC;">(</span>void<span style="color:#0000CC;">)</span> os_atomic_decrement_lint<span style="color:#0000CC;">(</span> <span style="color:#0000CC;">&</span>srv_conc<span style="color:#0000CC;">.</span>n_active<span style="color:#0000CC;">,</span> 1<span style="color:#0000CC;">)</span><span style="color:#0000CC;">;</span><br />
</li>
<li>
<span style="color:#0000CC;">}</span>
</li>
</ol>
</div>
</div>
</span><span style="font-size:14px;"><br />
1.<strong><span style="color:#E53333;">将当前活跃的线程数量加1</span></strong>:</span><br />
<span style="font-size:14px;">os_atomic_increment_lint(&srv_conc.n_active, 1)</span><br />
<span style="font-size:14px;">2.<span style="color:#E53333;"><strong>由于可能有很多thread 满足 srv_conc.n_active < (lint) srv_thread_concurrency 条件,从而进入执行os_atomic_increment_lint</strong></span></span><br />
<span style="font-size:14px;"><span style="color:#E53333;"><strong>但由于该语句是原子性,所以保证了每次加1必须是串行的。同时,加1完成之后,需要再一次的判断当前活跃的线程数是否超过了设置的innodb_thread_concurrency</strong></span>.</span><br />
<span style="font-size:14px;">bug:</span><br />
<span style="font-size:14px;">比如srv_thread_concurrency=3</span><br />
<br />
<br />
<span style="font-size:14px;">if (srv_conc.n_active < (lint) srv_thread_concurrency) {</span><br />
<span style="font-size:14px;"> ulint n_active;</span><br />
<span style="font-size:14px;">/*第一个thread 由于满足条件,将要开始执行n_active加1操作。(未执行) */</span><br />
<span style="font-size:14px;">/*第二个thread 由于满足条件,将要开始执行n_active加1操作。(未执行) */</span><br />
<span style="font-size:14px;">/*第三个thread 由于满足条件,将要开始执行n_active加1操作。(未执行) */</span><br />
<span style="font-size:14px;">/*第四个thread 由于满足条件,将要开始执行n_active加1操作。(未执行) */</span><br />
<span style="font-size:14px;">/*第五个thread 由于满足条件,将要开始执行n_active加1操作。(未执行) */</span><br />
<span style="font-size:14px;">/*第六个thread 由于满足条件,将要开始执行n_active加1操作。(未执行) */</span><br />
<span style="font-size:14px;"> </span><br />
<span style="font-size:14px;">/* Check if there are any free tickets. */</span><br />
<span style="font-size:14px;">n_active = os_atomic_increment_lint(&srv_conc.n_active, 1);<br />
</span><br />
<span style="font-size:14px;">/* 此时,上述6个线程依次加1,则n_active=6,下面代码尚未执行 */</span><br />
<span style="font-size:14px;">/*再次执行下面的判断时,由于不满足条件,从而进入sleep等待,等到下次sleep完之后,发现thread running queue已经满了,从而被误伤到.*/</span><br />
<br />
<span style="font-size:14px;"> if (n_active <= srv_thread_concurrency) {</span><br />
<span style="font-size:14px;"> ...</span><br />
<span style="font-size:14px;"> }</span><br />
<span style="font-size:14px;"> </span><br />
<span style="font-size:14px;">所以最好对n_active 进行加锁保护。</span><br />
<br />
<span style="font-size:14px;">3.<strong><span style="color:#E53333;">满足2的条件,如果该thread是由于之前sleep状态醒来,发现活跃线程数小于innodb_thread_concurrency,则将wating thread的数量减1.</span></strong></span><br />
<span style="font-size:14px;color:#E53333;"><strong>如果该thread之前有过一次sleep,且srv_thread_sleep_delay > 20,则将srv_thread_sleep_delay减1(系统不繁忙,可能sleep更短的时间就可以进入innodb了)。</strong></span><br />
<br />
<span style="font-size:14px;">4.<strong><span style="color:#E53333;">判断当前等待队列的情况(wating thread的个数),如果waiting thread的个数为0,说明目前等待队列非常空闲,设置srv_thread_sleep_delay为之前的1/2,<span style="font-size:14px;line-height:21px;white-space:normal;">表示系统很空闲。设置较小的值,避免因为偶尔的性能影响,较大的降低系统性能</span></span></strong></span><br />
<span style="font-size:14px;"> if (srv_conc.n_waiting == 0) {</span><br />
<span style="font-size:14px;"> srv_thread_sleep_delay >>= 1;</span><br />
<span style="font-size:14px;"> }</span><br />
<span style="font-size:14px;">。</span><br />
<span style="font-size:14px;"><br />
<strong><span style="color:#EE33EE;">总结</span></strong><strong><span style="color:#EE33EE;">:</span></strong></span><br />
<span style="font-size:14px;color:#64451D;"><strong>从上述代码中,我们可以很清楚的看到,通过系统的繁忙状态,来控制wating thread 进行sleep的时间。</strong></span><br />
<span style="font-size:14px;color:#64451D;"><strong>在系统比较繁忙的时候,sleep的时间相应增加,系统低负载的时候,sleep的时间相应减少,从而更加灵活的缓解系统的压力。</strong></span><br />
<span style="font-size:14px;color:#64451D;"><strong>srv_thread_sleep_delay的设置,过大可能导致系统在空闲时,由于稍微的抖动,导致系统性能显著下降。而设置过小,又会导致在</strong></span><br />
<span style="font-size:14px;color:#64451D;"><strong>在系统负载较大时,CPU切换频繁.如何合理的设置该值,需要进一步的测试报告。</strong></span><br />
<span style="font-size:14px;"> </span><br />
<div>
<br />
</div>mysql5.6对于thread_running_concurrency处理的源码分析
原文:http://blog.chinaunix.net/uid-20708886-id-5085516.html