advisory_rules_generic.php 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  1. <?php
  2. declare(strict_types=1);
  3. return [
  4. // Queries
  5. [
  6. 'id' => 'Uptime below one day',
  7. 'name' => __('Uptime below one day'),
  8. 'formula' => 'Uptime',
  9. 'test' => 'value < 86400',
  10. 'issue' => __('Uptime is less than 1 day, performance tuning may not be accurate.'),
  11. 'recommendation' => __(
  12. 'To have more accurate averages it is recommended to let the server run for'
  13. . ' longer than a day before running this analyzer'
  14. ),
  15. 'justification' => __('The uptime is only %s'),
  16. 'justification_formula' => 'ADVISOR_timespanFormat(Uptime)',
  17. ],
  18. [
  19. 'id' => 'Questions below 1,000',
  20. 'name' => __('Questions below 1,000'),
  21. 'formula' => 'Questions',
  22. 'test' => 'value < 1000',
  23. 'issue' => __(
  24. 'Fewer than 1,000 questions have been run against this server.'
  25. . ' The recommendations may not be accurate.'
  26. ),
  27. 'recommendation' => __(
  28. 'Let the server run for a longer time until it has executed a greater amount of queries.'
  29. ),
  30. 'justification' => __('Current amount of Questions: %s'),
  31. 'justification_formula' => 'Questions',
  32. ],
  33. [
  34. 'id' => 'Percentage of slow queries',
  35. 'name' => __('Percentage of slow queries'),
  36. 'precondition' => 'Questions > 0',
  37. 'formula' => 'Slow_queries / Questions * 100',
  38. 'test' => 'value >= 5',
  39. 'issue' => __('There is a lot of slow queries compared to the overall amount of Queries.'),
  40. 'recommendation' => __(
  41. 'You might want to increase {long_query_time}'
  42. . ' or optimize the queries listed in the slow query log'
  43. ),
  44. 'justification' => __('The slow query rate should be below 5%%, your value is %s%%.'),
  45. 'justification_formula' => 'round(value,2)',
  46. ],
  47. [
  48. 'id' => 'Slow query rate',
  49. 'name' => __('Slow query rate'),
  50. 'precondition' => 'Questions > 0',
  51. 'formula' => '(Slow_queries / Questions * 100) / Uptime',
  52. 'test' => 'value * 60 * 60 > 1',
  53. 'issue' => __('There is a high percentage of slow queries compared to the server uptime.'),
  54. 'recommendation' => __(
  55. 'You might want to increase {long_query_time}'
  56. . ' or optimize the queries listed in the slow query log'
  57. ),
  58. 'justification' => __('You have a slow query rate of %s per hour, you should have less than 1%% per hour.'),
  59. 'justification_formula' => 'ADVISOR_bytime(value,2)',
  60. ],
  61. [
  62. 'id' => 'Long query time',
  63. 'name' => __('Long query time'),
  64. 'formula' => 'long_query_time',
  65. 'test' => 'value >= 10',
  66. 'issue' => __(
  67. '{long_query_time} is set to 10 seconds or more,'
  68. . ' thus only slow queries that take above 10 seconds are logged.'
  69. ),
  70. 'recommendation' => __(
  71. 'It is suggested to set {long_query_time} to a lower value, depending on your environment.'
  72. . ' Usually a value of 1-5 seconds is suggested.'
  73. ),
  74. 'justification' => __('long_query_time is currently set to %ds.'),
  75. 'justification_formula' => 'value',
  76. ],
  77. [
  78. 'id' => 'Slow query logging',
  79. 'name' => __('Slow query logging'),
  80. 'precondition' => 'PMA_MYSQL_INT_VERSION < 50600',
  81. 'formula' => 'log_slow_queries',
  82. 'test' => 'value == \'OFF\'',
  83. 'issue' => __('The slow query log is disabled.'),
  84. 'recommendation' => __(
  85. 'Enable slow query logging by setting {log_slow_queries} to \'ON\'.'
  86. . ' This will help troubleshooting badly performing queries.'
  87. ),
  88. 'justification' => __('log_slow_queries is set to \'OFF\''),
  89. ],
  90. [
  91. 'id' => 'Slow query logging',
  92. 'name' => __('Slow query logging'),
  93. 'precondition' => 'PMA_MYSQL_INT_VERSION >= 50600',
  94. 'formula' => 'slow_query_log',
  95. 'test' => 'value == \'OFF\'',
  96. 'issue' => __('The slow query log is disabled.'),
  97. 'recommendation' => __(
  98. 'Enable slow query logging by setting {slow_query_log} to \'ON\'.'
  99. . ' This will help troubleshooting badly performing queries.'
  100. ),
  101. 'justification' => __('slow_query_log is set to \'OFF\''),
  102. ],
  103. // Versions
  104. [
  105. 'id' => 'Release Series',
  106. 'name' => __('Release Series'),
  107. 'formula' => 'version',
  108. 'test' => 'substr(value,0,2) <= \'5.\' && substr(value,2,1) < 1',
  109. 'issue' => __('The MySQL server version less than 5.1.'),
  110. 'recommendation' => __(
  111. 'You should upgrade, as MySQL 5.1 has improved performance, and MySQL 5.5 even more so.'
  112. ),
  113. 'justification' => __('Current version: %s'),
  114. 'justification_formula' => 'value',
  115. ],
  116. [
  117. 'id' => 'Minor Version',
  118. 'name' => __('Minor Version'),
  119. 'precondition' => '! fired(\'Release Series\')',
  120. 'formula' => 'version',
  121. 'test' => 'substr(value,0,2) <= \'5.\' && substr(value,2,1) <= 1 && substr(value,4,2) < 30',
  122. 'issue' => __('Version less than 5.1.30 (the first GA release of 5.1).'),
  123. 'recommendation' => __(
  124. 'You should upgrade, as recent versions of MySQL 5.1 have improved performance'
  125. . ' and MySQL 5.5 even more so.'
  126. ),
  127. 'justification' => __('Current version: %s'),
  128. 'justification_formula' => 'value',
  129. ],
  130. [
  131. 'id' => 'Minor Version',
  132. 'name' => __('Minor Version'),
  133. 'precondition' => '! fired(\'Release Series\')',
  134. 'formula' => 'version',
  135. 'test' => 'substr(value,0,1) == 5 && substr(value,2,1) == 5 && substr(value,4,2) < 8',
  136. 'issue' => __('Version less than 5.5.8 (the first GA release of 5.5).'),
  137. 'recommendation' => __('You should upgrade, to a stable version of MySQL 5.5.'),
  138. 'justification' => __('Current version: %s'),
  139. 'justification_formula' => 'value',
  140. ],
  141. [
  142. 'id' => 'Distribution',
  143. 'name' => __('Distribution'),
  144. 'formula' => 'version_comment',
  145. 'test' => 'preg_match(\'/source/i\',value)',
  146. 'issue' => __('Version is compiled from source, not a MySQL official binary.'),
  147. 'recommendation' => __(
  148. 'If you did not compile from source, you may be using a package modified by a distribution.'
  149. . ' The MySQL manual only is accurate for official MySQL binaries,'
  150. . ' not any package distributions (such as RedHat, Debian/Ubuntu etc).'
  151. ),
  152. 'justification' => __('\'source\' found in version_comment'),
  153. ],
  154. [
  155. 'id' => 'Distribution',
  156. 'name' => __('Distribution'),
  157. 'formula' => 'version_comment',
  158. 'test' => 'preg_match(\'/percona/i\',value)',
  159. 'issue' => __('The MySQL manual only is accurate for official MySQL binaries.'),
  160. 'recommendation' => __(
  161. 'Percona documentation is at <a href="https://www.percona.com/software/documentation/">'
  162. . 'https://www.percona.com/software/documentation/</a>'
  163. ),
  164. 'justification' => __('\'percona\' found in version_comment'),
  165. ],
  166. [
  167. 'id' => 'MySQL Architecture',
  168. 'name' => __('MySQL Architecture'),
  169. 'formula' => 'system_memory',
  170. 'test' => 'value > 3072*1024 && !preg_match(\'/64/\',version_compile_machine)'
  171. . ' && !preg_match(\'/64/\',version_compile_os)',
  172. 'issue' => __('MySQL is not compiled as a 64-bit package.'),
  173. 'recommendation' => __(
  174. 'Your memory capacity is above 3 GiB (assuming the Server is on localhost),'
  175. . ' so MySQL might not be able to access all of your memory.'
  176. . ' You might want to consider installing the 64-bit version of MySQL.'
  177. ),
  178. 'justification' => __('Available memory on this host: %s'),
  179. 'justification_formula' => 'ADVISOR_formatByteDown(value*1024, 2, 2)',
  180. ],
  181. // Query cache
  182. [
  183. 'id' => 'Query caching method',
  184. 'name' => __('Query caching method'),
  185. 'precondition' => '!fired(\'Query cache disabled\')',
  186. 'formula' => 'Questions / Uptime',
  187. 'test' => 'value > 100',
  188. 'issue' => __('Suboptimal caching method.'),
  189. 'recommendation' => __(
  190. 'You are using the MySQL Query cache with a fairly high traffic database.'
  191. . ' It might be worth considering to use '
  192. . '<a href="https://dev.mysql.com/doc/refman/5.6/en/ha-memcached.html">memcached</a>'
  193. . ' instead of the MySQL Query cache, especially if you have multiple slaves.'
  194. ),
  195. 'justification' => __(
  196. 'The query cache is enabled and the server receives %d queries per second.'
  197. . ' This rule fires if there is more than 100 queries per second.'
  198. ),
  199. 'justification_formula' => 'round(value,1)',
  200. ],
  201. // Sorts
  202. [
  203. 'id' => 'Percentage of sorts that cause temporary tables',
  204. 'name' => __('Percentage of sorts that cause temporary tables'),
  205. 'precondition' => 'Sort_scan + Sort_range > 0',
  206. 'formula' => 'Sort_merge_passes / (Sort_scan + Sort_range) * 100',
  207. 'test' => 'value > 10',
  208. 'issue' => __('Too many sorts are causing temporary tables.'),
  209. 'recommendation' => __(
  210. 'Consider increasing {sort_buffer_size} and/or {read_rnd_buffer_size},'
  211. . ' depending on your system memory limits.'
  212. ),
  213. 'justification' => __('%s%% of all sorts cause temporary tables, this value should be lower than 10%%.'),
  214. 'justification_formula' => 'round(value,1)',
  215. ],
  216. [
  217. 'id' => 'Rate of sorts that cause temporary tables',
  218. 'name' => __('Rate of sorts that cause temporary tables'),
  219. 'formula' => 'Sort_merge_passes / Uptime',
  220. 'test' => 'value * 60 * 60 > 1',
  221. 'issue' => __('Too many sorts are causing temporary tables.'),
  222. 'recommendation' => __(
  223. 'Consider increasing {sort_buffer_size} and/or {read_rnd_buffer_size},'
  224. . ' depending on your system memory limits.'
  225. ),
  226. 'justification' => __('Temporary tables average: %s, this value should be less than 1 per hour.'),
  227. 'justification_formula' => 'ADVISOR_bytime(value,2)',
  228. ],
  229. [
  230. 'id' => 'Sort rows',
  231. 'name' => __('Sort rows'),
  232. 'formula' => 'Sort_rows / Uptime',
  233. 'test' => 'value * 60 >= 1',
  234. 'issue' => __('There are lots of rows being sorted.'),
  235. 'recommendation' => __(
  236. 'While there is nothing wrong with a high amount of row sorting, you might want to'
  237. . ' make sure that the queries which require a lot of sorting use indexed columns in'
  238. . ' the ORDER BY clause, as this will result in much faster sorting.'
  239. ),
  240. 'justification' => __('Sorted rows average: %s'),
  241. 'justification_formula' => 'ADVISOR_bytime(value,2)',
  242. ],
  243. // Joins, scans
  244. [
  245. 'id' => 'Rate of joins without indexes',
  246. 'name' => __('Rate of joins without indexes'),
  247. 'formula' => '(Select_range_check + Select_scan + Select_full_join) / Uptime',
  248. 'test' => 'value * 60 * 60 > 1',
  249. 'issue' => __('There are too many joins without indexes.'),
  250. 'recommendation' => __(
  251. 'This means that joins are doing full table scans. Adding indexes for the columns being'
  252. . ' used in the join conditions will greatly speed up table joins.'
  253. ),
  254. 'justification' => __('Table joins average: %s, this value should be less than 1 per hour'),
  255. 'justification_formula' => 'ADVISOR_bytime(value,2)',
  256. ],
  257. [
  258. 'id' => 'Rate of reading first index entry',
  259. 'name' => __('Rate of reading first index entry'),
  260. 'formula' => 'Handler_read_first / Uptime',
  261. 'test' => 'value * 60 * 60 > 1',
  262. 'issue' => __('The rate of reading the first index entry is high.'),
  263. 'recommendation' => __(
  264. 'This usually indicates frequent full index scans. Full index scans are faster than'
  265. . ' table scans but require lots of CPU cycles in big tables, if those tables that have or'
  266. . ' had high volumes of UPDATEs and DELETEs, running \'OPTIMIZE TABLE\' might reduce the'
  267. . ' amount of and/or speed up full index scans. Other than that full index scans can'
  268. . ' only be reduced by rewriting queries.'
  269. ),
  270. 'justification' => __('Index scans average: %s, this value should be less than 1 per hour'),
  271. 'justification_formula' => 'ADVISOR_bytime(value,2)',
  272. ],
  273. [
  274. 'id' => 'Rate of reading fixed position',
  275. 'name' => __('Rate of reading fixed position'),
  276. 'formula' => 'Handler_read_rnd / Uptime',
  277. 'test' => 'value * 60 * 60 > 1',
  278. 'issue' => __('The rate of reading data from a fixed position is high.'),
  279. 'recommendation' => __(
  280. 'This indicates that many queries need to sort results and/or do a full table scan,'
  281. . ' including join queries that do not use indexes. Add indexes where applicable.'
  282. ),
  283. 'justification' => __('Rate of reading fixed position average: %s, this value should be less than 1 per hour'),
  284. 'justification_formula' => 'ADVISOR_bytime(value,2)',
  285. ],
  286. [
  287. 'id' => 'Rate of reading next table row',
  288. 'name' => __('Rate of reading next table row'),
  289. 'formula' => 'Handler_read_rnd_next / Uptime',
  290. 'test' => 'value * 60 * 60 > 1',
  291. 'issue' => __('The rate of reading the next table row is high.'),
  292. 'recommendation' => __(
  293. 'This indicates that many queries are doing full table scans. Add indexes where applicable.'
  294. ),
  295. 'justification' => __('Rate of reading next table row: %s, this value should be less than 1 per hour'),
  296. 'justification_formula' => 'ADVISOR_bytime(value,2)',
  297. ],
  298. // Temp tables
  299. [
  300. 'id' => 'Different tmp_table_size and max_heap_table_size',
  301. 'name' => __('Different tmp_table_size and max_heap_table_size'),
  302. 'formula' => 'tmp_table_size - max_heap_table_size',
  303. 'test' => 'value !=0',
  304. 'issue' => __('{tmp_table_size} and {max_heap_table_size} are not the same.'),
  305. 'recommendation' => __(
  306. 'If you have deliberately changed one of either: The server uses the lower value of either'
  307. . ' to determine the maximum size of in-memory tables. So if you wish to increase the'
  308. . ' in-memory table limit you will have to increase the other value as well.'
  309. ),
  310. 'justification' => __('Current values are tmp_table_size: %s, max_heap_table_size: %s'),
  311. 'justification_formula' => 'ADVISOR_formatByteDown(tmp_table_size, 2, 2),'
  312. . ' ADVISOR_formatByteDown(max_heap_table_size, 2, 2)',
  313. ],
  314. [
  315. 'id' => 'Percentage of temp tables on disk',
  316. 'name' => __('Percentage of temp tables on disk'),
  317. 'precondition' => 'Created_tmp_tables + Created_tmp_disk_tables > 0',
  318. 'formula' => 'Created_tmp_disk_tables / (Created_tmp_tables + Created_tmp_disk_tables) * 100',
  319. 'test' => 'value > 25',
  320. 'issue' => __('Many temporary tables are being written to disk instead of being kept in memory.'),
  321. 'recommendation' => __(
  322. 'Increasing {max_heap_table_size} and {tmp_table_size} might help. However some'
  323. . ' temporary tables are always being written to disk, independent of the value of these variables.'
  324. . ' To eliminate these you will have to rewrite your queries to avoid those conditions'
  325. . ' (Within a temporary table: Presence of a BLOB or TEXT column or presence of a column'
  326. . ' bigger than 512 bytes) as mentioned in the beginning of an <a href="'
  327. . 'https://www.facebook.com/note.php?note_id=10150111255065841&comments'
  328. . '">Article by the Pythian Group</a>'
  329. ),
  330. 'justification' => __(
  331. '%s%% of all temporary tables are being written to disk, this value should be below 25%%'
  332. ),
  333. 'justification_formula' => 'round(value,1)',
  334. ],
  335. [
  336. 'id' => 'Temp disk rate',
  337. 'name' => __('Temp disk rate'),
  338. 'precondition' => '!fired(\'Percentage of temp tables on disk\')',
  339. 'formula' => 'Created_tmp_disk_tables / Uptime',
  340. 'test' => 'value * 60 * 60 > 1',
  341. 'issue' => __('Many temporary tables are being written to disk instead of being kept in memory.'),
  342. 'recommendation' => __(
  343. 'Increasing {max_heap_table_size} and {tmp_table_size} might help. However some'
  344. . ' temporary tables are always being written to disk, independent of the value of these variables.'
  345. . ' To eliminate these you will have to rewrite your queries to avoid those conditions'
  346. . ' (Within a temporary table: Presence of a BLOB or TEXT column or presence of a column'
  347. . ' bigger than 512 bytes) as mentioned in the <a href="'
  348. . 'https://dev.mysql.com/doc/refman/8.0/en/internal-temporary-tables.html'
  349. . '">MySQL Documentation</a>'
  350. ),
  351. 'justification' => __(
  352. 'Rate of temporary tables being written to disk: %s, this value should be less than 1 per hour'
  353. ),
  354. 'justification_formula' => 'ADVISOR_bytime(value,2)',
  355. ],
  356. // MyISAM index cache
  357. [
  358. 'id' => 'MyISAM key buffer size',
  359. 'name' => __('MyISAM key buffer size'),
  360. 'formula' => 'key_buffer_size',
  361. 'test' => 'value == 0',
  362. 'issue' => __('Key buffer is not initialized. No MyISAM indexes will be cached.'),
  363. 'recommendation' => __(
  364. 'Set {key_buffer_size} depending on the size of your MyISAM indexes. 64M is a good start.'
  365. ),
  366. 'justification' => __('key_buffer_size is 0'),
  367. ],
  368. [
  369. 'id' => 'Max % MyISAM key buffer ever used',
  370. /* xgettext:no-php-format */
  371. 'name' => __('Max % MyISAM key buffer ever used'),
  372. 'precondition' => 'key_buffer_size > 0',
  373. 'formula' => 'Key_blocks_used * key_cache_block_size / key_buffer_size * 100',
  374. 'test' => 'value < 95',
  375. /* xgettext:no-php-format */
  376. 'issue' => __('MyISAM key buffer (index cache) % used is low.'),
  377. 'recommendation' => __(
  378. 'You may need to decrease the size of {key_buffer_size}, re-examine your tables to see'
  379. . ' if indexes have been removed, or examine queries and expectations'
  380. . ' about what indexes are being used.'
  381. ),
  382. 'justification' => __('max %% MyISAM key buffer ever used: %s%%, this value should be above 95%%'),
  383. 'justification_formula' => 'round(value,1)',
  384. ],
  385. [
  386. 'id' => 'Percentage of MyISAM key buffer used',
  387. 'name' => __('Percentage of MyISAM key buffer used'),
  388. // Don't fire if above rule fired - we don't need the same advice twice
  389. 'precondition' => 'key_buffer_size > 0 && !fired(\'Max % MyISAM key buffer ever used\')',
  390. 'formula' => '( 1 - Key_blocks_unused * key_cache_block_size / key_buffer_size) * 100',
  391. 'test' => 'value < 95',
  392. /* xgettext:no-php-format */
  393. 'issue' => __('MyISAM key buffer (index cache) % used is low.'),
  394. 'recommendation' => __(
  395. 'You may need to decrease the size of {key_buffer_size}, re-examine your tables to see'
  396. . ' if indexes have been removed, or examine queries and expectations'
  397. . ' about what indexes are being used.'
  398. ),
  399. 'justification' => __('%% MyISAM key buffer used: %s%%, this value should be above 95%%'),
  400. 'justification_formula' => 'round(value,1)',
  401. ],
  402. [
  403. 'id' => 'Percentage of index reads from memory',
  404. 'name' => __('Percentage of index reads from memory'),
  405. 'precondition' => 'Key_read_requests > 0',
  406. 'formula' => '100 - (Key_reads / Key_read_requests * 100)',
  407. 'test' => 'value < 95',
  408. /* xgettext:no-php-format */
  409. 'issue' => __('The % of indexes that use the MyISAM key buffer is low.'),
  410. 'recommendation' => __('You may need to increase {key_buffer_size}.'),
  411. 'justification' => __('Index reads from memory: %s%%, this value should be above 95%%'),
  412. 'justification_formula' => 'round(value,1)',
  413. ],
  414. // Other caches
  415. [
  416. 'id' => 'Rate of table open',
  417. 'name' => __('Rate of table open'),
  418. 'formula' => 'Opened_tables / Uptime',
  419. 'test' => 'value*60*60 > 10',
  420. 'issue' => __('The rate of opening tables is high.'),
  421. 'recommendation' => __(
  422. 'Opening tables requires disk I/O which is costly.'
  423. . ' Increasing {table_open_cache} might avoid this.'
  424. ),
  425. 'justification' => __('Opened table rate: %s, this value should be less than 10 per hour'),
  426. 'justification_formula' => 'ADVISOR_bytime(value,2)',
  427. ],
  428. [
  429. 'id' => 'Percentage of used open files limit',
  430. 'name' => __('Percentage of used open files limit'),
  431. 'formula' => 'Open_files / open_files_limit * 100',
  432. 'test' => 'value > 85',
  433. 'issue' => __(
  434. 'The number of open files is approaching the max number of open files.'
  435. . ' You may get a "Too many open files" error.'
  436. ),
  437. 'recommendation' => __(
  438. 'Consider increasing {open_files_limit}, and check the error log when'
  439. . ' restarting after changing {open_files_limit}.'
  440. ),
  441. 'justification' => __('The number of opened files is at %s%% of the limit. It should be below 85%%'),
  442. 'justification_formula' => 'round(value,1)',
  443. ],
  444. [
  445. 'id' => 'Rate of open files',
  446. 'name' => __('Rate of open files'),
  447. 'formula' => 'Open_files / Uptime',
  448. 'test' => 'value * 60 * 60 > 5',
  449. 'issue' => __('The rate of opening files is high.'),
  450. 'recommendation' => __(
  451. 'Consider increasing {open_files_limit}, and check the error log when'
  452. . ' restarting after changing {open_files_limit}.'
  453. ),
  454. 'justification' => __('Opened files rate: %s, this value should be less than 5 per hour'),
  455. 'justification_formula' => 'ADVISOR_bytime(value,2)',
  456. ],
  457. [
  458. 'id' => 'Immediate table locks %',
  459. /* xgettext:no-php-format */
  460. 'name' => __('Immediate table locks %'),
  461. 'precondition' => 'Table_locks_waited + Table_locks_immediate > 0',
  462. 'formula' => 'Table_locks_immediate / (Table_locks_waited + Table_locks_immediate) * 100',
  463. 'test' => 'value < 95',
  464. 'issue' => __('Too many table locks were not granted immediately.'),
  465. 'recommendation' => __('Optimize queries and/or use InnoDB to reduce lock wait.'),
  466. 'justification' => __('Immediate table locks: %s%%, this value should be above 95%%'),
  467. 'justification_formula' => 'round(value,1)',
  468. ],
  469. [
  470. 'id' => 'Table lock wait rate',
  471. 'name' => __('Table lock wait rate'),
  472. 'formula' => 'Table_locks_waited / Uptime',
  473. 'test' => 'value * 60 * 60 > 1',
  474. 'issue' => __('Too many table locks were not granted immediately.'),
  475. 'recommendation' => __('Optimize queries and/or use InnoDB to reduce lock wait.'),
  476. 'justification' => __('Table lock wait rate: %s, this value should be less than 1 per hour'),
  477. 'justification_formula' => 'ADVISOR_bytime(value,2)',
  478. ],
  479. [
  480. 'id' => 'Thread cache',
  481. 'name' => __('Thread cache'),
  482. 'formula' => 'thread_cache_size',
  483. 'test' => 'value < 1',
  484. 'issue' => __('Thread cache is disabled, resulting in more overhead from new connections to MySQL.'),
  485. 'recommendation' => __('Enable the thread cache by setting {thread_cache_size} > 0.'),
  486. 'justification' => __('The thread cache is set to 0'),
  487. ],
  488. [
  489. 'id' => 'Thread cache hit rate %',
  490. /* xgettext:no-php-format */
  491. 'name' => __('Thread cache hit rate %'),
  492. 'precondition' => 'thread_cache_size > 0',
  493. 'formula' => '100 - Threads_created / Connections',
  494. 'test' => 'value < 80',
  495. 'issue' => __('Thread cache is not efficient.'),
  496. 'recommendation' => __('Increase {thread_cache_size}.'),
  497. 'justification' => __('Thread cache hitrate: %s%%, this value should be above 80%%'),
  498. 'justification_formula' => 'round(value,1)',
  499. ],
  500. [
  501. 'id' => 'Threads that are slow to launch',
  502. 'name' => __('Threads that are slow to launch'),
  503. 'precondition' => 'slow_launch_time > 0',
  504. 'formula' => 'Slow_launch_threads',
  505. 'test' => 'value > 0',
  506. 'issue' => __('There are too many threads that are slow to launch.'),
  507. 'recommendation' => __(
  508. 'This generally happens in case of general system overload as it is pretty simple'
  509. . ' operations. You might want to monitor your system load carefully.'
  510. ),
  511. 'justification' => __('%s thread(s) took longer than %s seconds to start, it should be 0'),
  512. 'justification_formula' => 'value, slow_launch_time',
  513. ],
  514. [
  515. 'id' => 'Slow launch time',
  516. 'name' => __('Slow launch time'),
  517. 'formula' => 'slow_launch_time',
  518. 'test' => 'value > 2',
  519. 'issue' => __('Slow_launch_time is above 2s.'),
  520. 'recommendation' => __(
  521. 'Set {slow_launch_time} to 1s or 2s to correctly count threads that are slow to launch.'
  522. ),
  523. 'justification' => __('slow_launch_time is set to %s'),
  524. 'justification_formula' => 'value',
  525. ],
  526. // Connections
  527. [
  528. 'id' => 'Percentage of used connections',
  529. 'name' => __('Percentage of used connections'),
  530. 'formula' => 'Max_used_connections / max_connections * 100',
  531. 'test' => 'value > 80',
  532. 'issue' => __(
  533. 'The maximum amount of used connections is getting close to the value of {max_connections}.'
  534. ),
  535. 'recommendation' => __(
  536. 'Increase {max_connections}, or decrease {wait_timeout} so that connections that do not'
  537. . ' close database handlers properly get killed sooner.'
  538. . ' Make sure the code closes database handlers properly.'
  539. ),
  540. 'justification' => __('Max_used_connections is at %s%% of max_connections, it should be below 80%%'),
  541. 'justification_formula' => 'round(value,1)',
  542. ],
  543. [
  544. 'id' => 'Percentage of aborted connections',
  545. 'name' => __('Percentage of aborted connections'),
  546. 'formula' => 'Aborted_connects / Connections * 100',
  547. 'test' => 'value > 1',
  548. 'issue' => __('Too many connections are aborted.'),
  549. 'recommendation' => __(
  550. 'Connections are usually aborted when they cannot be authorized. <a href="'
  551. . 'https://www.percona.com/blog/2008/08/23/how-to-track-down-the-source-of-aborted_connects/'
  552. . '">This article</a> might help you track down the source.'
  553. ),
  554. 'justification' => __('%s%% of all connections are aborted. This value should be below 1%%'),
  555. 'justification_formula' => 'round(value,1)',
  556. ],
  557. [
  558. 'id' => 'Rate of aborted connections',
  559. 'name' => __('Rate of aborted connections'),
  560. 'formula' => 'Aborted_connects / Uptime',
  561. 'test' => 'value * 60 * 60 > 1',
  562. 'issue' => __('Too many connections are aborted.'),
  563. 'recommendation' => __(
  564. 'Connections are usually aborted when they cannot be authorized. <a href="'
  565. . 'https://www.percona.com/blog/2008/08/23/how-to-track-down-the-source-of-aborted_connects/'
  566. . '">This article</a> might help you track down the source.'
  567. ),
  568. 'justification' => __('Aborted connections rate is at %s, this value should be less than 1 per hour'),
  569. 'justification_formula' => 'ADVISOR_bytime(value,2)',
  570. ],
  571. [
  572. 'id' => 'Percentage of aborted clients',
  573. 'name' => __('Percentage of aborted clients'),
  574. 'formula' => 'Aborted_clients / Connections * 100',
  575. 'test' => 'value > 2',
  576. 'issue' => __('Too many clients are aborted.'),
  577. 'recommendation' => __(
  578. 'Clients are usually aborted when they did not close their connection to MySQL properly.'
  579. . ' This can be due to network issues or code not closing a database handler properly.'
  580. . ' Check your network and code.'
  581. ),
  582. 'justification' => __('%s%% of all clients are aborted. This value should be below 2%%'),
  583. 'justification_formula' => 'round(value,1)',
  584. ],
  585. [
  586. 'id' => 'Rate of aborted clients',
  587. 'name' => __('Rate of aborted clients'),
  588. 'formula' => 'Aborted_clients / Uptime',
  589. 'test' => 'value * 60 * 60 > 1',
  590. 'issue' => __('Too many clients are aborted.'),
  591. 'recommendation' => __(
  592. 'Clients are usually aborted when they did not close their connection to MySQL properly.'
  593. . ' This can be due to network issues or code not closing a database handler properly.'
  594. . ' Check your network and code.'
  595. ),
  596. 'justification' => __('Aborted client rate is at %s, this value should be less than 1 per hour'),
  597. 'justification_formula' => 'ADVISOR_bytime(value,2)',
  598. ],
  599. // InnoDB
  600. [
  601. 'id' => 'Is InnoDB disabled?',
  602. 'name' => __('Is InnoDB disabled?'),
  603. 'precondition' => 'PMA_MYSQL_INT_VERSION < 50600',
  604. 'formula' => 'have_innodb',
  605. 'test' => 'value != "YES"',
  606. 'issue' => __('You do not have InnoDB enabled.'),
  607. 'recommendation' => __('InnoDB is usually the better choice for table engines.'),
  608. 'justification' => __('have_innodb is set to \'value\''),
  609. ],
  610. [
  611. 'id' => 'InnoDB log size',
  612. 'name' => __('InnoDB log size'),
  613. 'precondition' => 'innodb_buffer_pool_size > 0',
  614. 'formula' => '(innodb_log_file_size * innodb_log_files_in_group)/ innodb_buffer_pool_size * 100',
  615. 'test' => 'value < 20 && innodb_log_file_size / (1024 * 1024) < 256',
  616. 'issue' => __(
  617. 'The InnoDB log file size is not an appropriate size, in relation to the InnoDB buffer pool.'
  618. ),
  619. 'recommendation' => __(/* xgettext:no-php-format */
  620. 'Especially on a system with a lot of writes to InnoDB tables you should set'
  621. . ' {innodb_log_file_size} to 25% of {innodb_buffer_pool_size}. However the bigger this value,'
  622. . ' the longer the recovery time will be when database crashes, so this value should not be set'
  623. . ' much higher than 256 MiB. Please note however that you cannot simply change the value of'
  624. . ' this variable. You need to shutdown the server, remove the InnoDB log files, set the new'
  625. . ' value in my.cnf, start the server, then check the error logs if everything went fine.'
  626. . ' See also <a href="'
  627. . 'https://mysqldatabaseadministration.blogspot.com/2007/01/increase-innodblogfilesize-proper-way.html'
  628. . '">this blog entry</a>'
  629. ),
  630. 'justification' => __(
  631. 'Your InnoDB log size is at %s%% in relation to the InnoDB buffer pool size,'
  632. . ' it should not be below 20%%'
  633. ),
  634. 'justification_formula' => 'round(value,1)',
  635. ],
  636. [
  637. 'id' => 'Max InnoDB log size',
  638. 'name' => __('Max InnoDB log size'),
  639. 'precondition' => 'innodb_buffer_pool_size > 0 && innodb_log_file_size / innodb_buffer_pool_size * 100 < 30',
  640. 'formula' => 'innodb_log_file_size / (1024 * 1024)',
  641. 'test' => 'value > 256',
  642. 'issue' => __('The InnoDB log file size is inadequately large.'),
  643. 'recommendation' => __(/* xgettext:no-php-format */
  644. 'It is usually sufficient to set {innodb_log_file_size} to 25% of the size of'
  645. . ' {innodb_buffer_pool_size}. A very big {innodb_log_file_size} slows down the recovery'
  646. . ' time after a database crash considerably. See also '
  647. . '<a href="https://www.percona.com/blog/2006/07/03/choosing-proper-innodb_log_file_size/">'
  648. . 'this Article</a>. You need to shutdown the server, remove the InnoDB log files, set the'
  649. . ' new value in my.cnf, start the server, then check the error logs'
  650. . ' if everything went fine. See also <a href="'
  651. . 'https://mysqldatabaseadministration.blogspot.com/2007/01/increase-innodblogfilesize-proper-way.html'
  652. . '">this blog entry</a>'
  653. ),
  654. 'justification' => __('Your absolute InnoDB log size is %s MiB'),
  655. 'justification_formula' => 'round(value,1)',
  656. ],
  657. [
  658. 'id' => 'InnoDB buffer pool size',
  659. 'name' => __('InnoDB buffer pool size'),
  660. 'precondition' => 'system_memory > 0',
  661. 'formula' => 'innodb_buffer_pool_size / system_memory * 100',
  662. 'test' => 'value < 60',
  663. 'issue' => __('Your InnoDB buffer pool is fairly small.'),
  664. 'recommendation' => __(/* xgettext:no-php-format */
  665. 'The InnoDB buffer pool has a profound impact on performance for InnoDB tables.'
  666. . ' Assign all your remaining memory to this buffer. For database servers that use solely InnoDB'
  667. . ' as storage engine and have no other services (e.g. a web server) running, you may set this'
  668. . ' as high as 80% of your available memory. If that is not the case, you need to carefully'
  669. . ' assess the memory consumption of your other services and non-InnoDB-Tables and set this'
  670. . ' variable accordingly. If it is set too high, your system will start swapping,'
  671. . ' which decreases performance significantly. See also '
  672. . '<a href="https://www.percona.com/blog/2007/11/03/choosing-innodb_buffer_pool_size/">this article</a>'
  673. ),
  674. 'justification' => __(
  675. 'You are currently using %s%% of your memory for the InnoDB buffer pool.'
  676. . ' This rule fires if you are assigning less than 60%%, however this might be perfectly'
  677. . ' adequate for your system if you don\'t have much InnoDB tables'
  678. . ' or other services running on the same machine.'
  679. ),
  680. 'justification_formula' => 'value',
  681. ],
  682. // Other
  683. [
  684. 'id' => 'MyISAM concurrent inserts',
  685. 'name' => __('MyISAM concurrent inserts'),
  686. 'formula' => 'concurrent_insert',
  687. 'test' => 'value === 0 || value === \'NEVER\'',
  688. 'issue' => __('Enable {concurrent_insert} by setting it to 1'),
  689. 'recommendation' => __(
  690. 'Setting {concurrent_insert} to 1 reduces contention between'
  691. . ' readers and writers for a given table. See also '
  692. . '<a href="https://dev.mysql.com/doc/refman/5.5/en/concurrent-inserts.html">MySQL Documentation</a>'
  693. ),
  694. 'justification' => __('concurrent_insert is set to 0'),
  695. ],
  696. ];