From b4fb6251ce418d457f883f6a43648adbb26492d2 Mon Sep 17 00:00:00 2001 From: Luciano Righetti Date: Tue, 19 Jul 2022 13:36:53 +0200 Subject: [PATCH] new: mysql db tuning recommendations in server diagnostics --- app/Controller/ServersController.php | 15 +++- app/Model/Server.php | 82 +++++++++++++++++++ .../healthElements/db_config_diagnostic.ctp | 40 +++++++++ .../Elements/healthElements/diagnostics.ctp | 6 ++ 4 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 app/View/Elements/healthElements/db_config_diagnostic.ctp diff --git a/app/Controller/ServersController.php b/app/Controller/ServersController.php index a9bea9948..c25ff879f 100644 --- a/app/Controller/ServersController.php +++ b/app/Controller/ServersController.php @@ -1146,6 +1146,7 @@ class ServersController extends AppController // get the DB diagnostics $dbDiagnostics = $this->Server->dbSpaceUsage(); $dbSchemaDiagnostics = $this->Server->dbSchemaDiagnostic(); + $dbConfiguration = $this->Server->dbConfiguration(); $redisInfo = $this->Server->redisInfo(); @@ -1166,7 +1167,7 @@ class ServersController extends AppController $securityAudit = (new SecurityAudit())->run($this->Server); - $view = compact('gpgStatus', 'sessionErrors', 'proxyStatus', 'sessionStatus', 'zmqStatus', 'moduleStatus', 'yaraStatus', 'gpgErrors', 'proxyErrors', 'zmqErrors', 'stix', 'moduleErrors', 'moduleTypes', 'dbDiagnostics', 'dbSchemaDiagnostics', 'redisInfo', 'attachmentScan', 'securityAudit'); + $view = compact('gpgStatus', 'sessionErrors', 'proxyStatus', 'sessionStatus', 'zmqStatus', 'moduleStatus', 'yaraStatus', 'gpgErrors', 'proxyErrors', 'zmqErrors', 'stix', 'moduleErrors', 'moduleTypes', 'dbDiagnostics', 'dbSchemaDiagnostics', 'dbConfiguration', 'redisInfo', 'attachmentScan', 'securityAudit'); } else { $view = []; } @@ -1207,6 +1208,7 @@ class ServersController extends AppController 'readableFiles' => $readableFiles, 'dbDiagnostics' => $dbDiagnostics, 'dbSchemaDiagnostics' => $dbSchemaDiagnostics, + 'dbConfiguration' => $dbConfiguration, 'redisInfo' => $redisInfo, 'finalSettings' => $dumpResults, 'extensions' => $extensions, @@ -2205,6 +2207,17 @@ class ServersController extends AppController } } + public function dbConfiguration() + { + $dbConfiguration = $this->Server->dbConfiguration(); + if ($this->_isRest()) { + return $this->RestResponse->viewData($dbConfiguration, $this->response->type()); + } else { + $this->set('dbConfiguration', $dbConfiguration); + $this->render('/Elements/healthElements/db_config_diagnostic'); + } + } + public function cspReport() { if (!$this->request->is('post')) { diff --git a/app/Model/Server.php b/app/Model/Server.php index 53ea48258..912c6fd2f 100644 --- a/app/Model/Server.php +++ b/app/Model/Server.php @@ -132,6 +132,59 @@ class Server extends AppModel public $syncTestErrorCodes = array(); + const MYSQL_RECOMMENDED_SETTINGS = [ + 'INNODB_BUFFER_POOL_SIZE' => [ + 'default' => '134217728', + 'recommended' => '2147483648', + 'explanation' => 'The InnoDB buffer pool is the memory area where caches table and index data reside. It is the most important MySQL setting, in a dedicated server it should be around 3/4 of all the available RAM. In a shared server it should be around 1/2 of the available RAM.', + ], + 'INNODB_DEDICATED_SERVER' => [ + 'default' => '0', + 'recommended' => '', + 'explanation' => 'Set to `1` if the database is running in a dedicated server. The database engine will examine the available memory and dynamically set `innodb_buffer_pool_size`, `innodb_log_file_size`, `innodb_log_files_in_group` and `innodb_flush_method`. It is particularly useful in cloud enviroments that can be auto-scaled.', + ], + 'INNODB_LOG_FILE_SIZE' => [ + 'default' => '100663296', + 'recommended' => '629145600', + 'explanation' => 'This parameter determines the fixed size for MySQLs redo logs. Tuning this value affects the crash recovery time and also overall system performance.', + ], + 'INNODB_LOG_FILES_IN_GROUP' => [ + 'default' => '2', + 'recommended' => '2', + 'explanation' => 'Defines the number of log files in the log group.', + ], + 'INNODB_CHANGE_BUFFERING' => [ + 'default' => 'none', + 'recommended' => 'none', + 'explanation' => 'Whether InnoDB performs change buffering, an optimization that delays write operations to secondary indexes so that the I/O operations can be performed sequentially, enabling it causes extremely long shutdown times for upgrades.', + ], + 'INNODB_IO_CAPACITY' => [ + 'default' => '200', + 'recommended' => '1000', + 'explanation' => 'Defines the number of I/O operations per second (IOPS) available to InnoDB background tasks, such as flushing pages from the buffer pool and merging data from the change buffer.', + ], + 'INNODB_IO_CAPACITY_MAX' => [ + 'default' => '2000', + 'recommended' => '2000', + 'explanation' => 'If flushing activity falls behind, InnoDB can flush more aggressively, at a higher rate of I/O operations per second (IOPS) than defined by the `innodb_io_capacity variable`.', + ], + 'INNODB_STATS_PERSISTENT' => [ + 'default' => 'ON', + 'recommended' => 'ON', + 'explanation' => 'Specifies whether InnoDB index statistics are persisted to disk. Otherwise, statistics may be recalculated frequently which can lead to variations in query execution plans.', + ], + 'INNODB_READ_IO_THREADS' => [ + 'default' => '4', + 'recommended' => '16', + 'explanation' => 'The number of I/O threads for read operations in InnoDB.', + ], + 'INNODB_WRITE_IO_THREADS' => [ + 'default' => '4', + 'recommended' => '4', + 'explanation' => 'The number of I/O threads for write operations in InnoDB.', + ], + ]; + public function __construct($id = false, $table = null, $ds = null) { parent::__construct($id, $table, $ds); @@ -2717,6 +2770,35 @@ class Server extends AppModel return $schemaDiagnostic; } + /* + * Get RDBMS configuration values + */ + public function dbConfiguration(): array + { + if ($this->isMysql()) { + $configuration = []; + + $dbVariables = $this->query("SELECT VARIABLE_NAME, VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES;"); + $settings = array_keys(self::MYSQL_RECOMMENDED_SETTINGS); + + foreach ($dbVariables as $dbVariable) { + if (in_array($dbVariable['GLOBAL_VARIABLES']['VARIABLE_NAME'], $settings)) { + $configuration[] = [ + 'name' => $dbVariable['GLOBAL_VARIABLES']['VARIABLE_NAME'], + 'value' => $dbVariable['GLOBAL_VARIABLES']['VARIABLE_VALUE'], + 'default' => self::MYSQL_RECOMMENDED_SETTINGS[$dbVariable['GLOBAL_VARIABLES']['VARIABLE_NAME']]['default'], + 'recommended' => self::MYSQL_RECOMMENDED_SETTINGS[$dbVariable['GLOBAL_VARIABLES']['VARIABLE_NAME']]['recommended'], + 'explanation' => self::MYSQL_RECOMMENDED_SETTINGS[$dbVariable['GLOBAL_VARIABLES']['VARIABLE_NAME']]['explanation'], + ]; + } + } + + return $configuration; + } else { + return []; + } + } + /* * Work in progress, still needs DEFAULT in the schema for it to work correctly * Currently only works for missing_column and column_different diff --git a/app/View/Elements/healthElements/db_config_diagnostic.ctp b/app/View/Elements/healthElements/db_config_diagnostic.ctp new file mode 100644 index 000000000..ae7a0f6f4 --- /dev/null +++ b/app/View/Elements/healthElements/db_config_diagnostic.ctp @@ -0,0 +1,40 @@ +
+ element('/genericElements/IndexTable/index_table', array( + 'data' => array( + 'data' => $dbConfiguration, + 'skip_pagination' => 1, + 'fields' => array( + array( + 'name' => __('Setting'), + 'data_path' => 'name' + ), + array( + 'name' => __('Default'), + 'class' => 'align-left', + 'header_class' => 'align-left', + 'data_path' => 'default' + ), + array( + 'name' => __('Current'), + 'class' => 'align-left', + 'header_class' => 'align-left', + 'data_path' => 'value', + ), + array( + 'name' => __('Recommended'), + 'class' => 'align-left', + 'header_class' => 'align-left', + 'data_path' => 'recommended' + ), + array( + 'name' => __('Explanation'), + 'header_class' => 'align-left', + 'data_path' => 'explanation' + ), + ), + 'title' => __('SQL database configuration'), + 'description' => __('Best practices for configuring RDBMS parameters for performance.'), + ) + )); + ?> +
\ No newline at end of file diff --git a/app/View/Elements/healthElements/diagnostics.ctp b/app/View/Elements/healthElements/diagnostics.ctp index 358963a6c..9bed45c67 100644 --- a/app/View/Elements/healthElements/diagnostics.ctp +++ b/app/View/Elements/healthElements/diagnostics.ctp @@ -281,6 +281,12 @@ )); ?> + + element('/healthElements/db_config_diagnostic', array( + 'dbConfiguration' => $dbConfiguration + )); ?> + +

: ' . __('Not installed.') . '') ?>