From bda27479a45b69eff58a46a73813b1cc331bba8e Mon Sep 17 00:00:00 2001 From: James Page Date: Thu, 2 Mar 2017 10:34:31 +0000 Subject: [PATCH] Add tuning-level configuration option Inline with the mysql charm, add a tuning-level configuration option that allows end users to change the configuration profile for PXC. This option supports three values safest (default): use configuration options with best data integrity guarantees. fast: compromise some data integrity guarantees to improve performance. unsafe: pretty much throw away all data integrity guarantees to maximise performance. In clustered deployments, 'fast' and 'unsafe' may be appropriate to use but should be considered carefully before reconfiguration away from the default 'safest' option. Right now, this option tweaks the innodb_flush_log_at_trx_commit value for PXC: safest (default): 1 fast: 2 unsafe: 0 but should be used for other tuning optimizations that come along in the future. Also add direct configuration options for: innodb-change-buffering innodb-io-capacity to allow end users to tweak other performance optimizations that we can't yet do automatically using charm options. This commit also includes a resync of charm-helpers, which includes the fix to flush priviledges after adding grants to resolve bug 1513239. Change-Id: I7c31e3bfbb825ae7091913e678dd1b7893892d1d Closes-Bug: 1599222 Closes-Bug: 1513239 --- charmhelpers/contrib/charmsupport/nrpe.py | 29 +++++++++----- charmhelpers/contrib/database/mysql.py | 36 ++++++++++++++++- config.yaml | 47 +++++++++++++++++++++++ templates/my.cnf | 14 +++++++ templates/mysqld.cnf | 14 +++++++ 5 files changed, 129 insertions(+), 11 deletions(-) diff --git a/charmhelpers/contrib/charmsupport/nrpe.py b/charmhelpers/contrib/charmsupport/nrpe.py index 1410512..e095d41 100644 --- a/charmhelpers/contrib/charmsupport/nrpe.py +++ b/charmhelpers/contrib/charmsupport/nrpe.py @@ -338,13 +338,14 @@ def get_nagios_unit_name(relation_name='nrpe-external-master'): return unit -def add_init_service_checks(nrpe, services, unit_name): +def add_init_service_checks(nrpe, services, unit_name, immediate_check=True): """ Add checks for each service in list :param NRPE nrpe: NRPE object to add check to :param list services: List of services to check :param str unit_name: Unit name to use in check description + :param bool immediate_check: For sysv init, run the service check immediately """ for svc in services: # Don't add a check for these services from neutron-gateway @@ -368,21 +369,29 @@ def add_init_service_checks(nrpe, services, unit_name): ) elif os.path.exists(sysv_init): cronpath = '/etc/cron.d/nagios-service-check-%s' % svc - cron_file = ('*/5 * * * * root ' - '/usr/local/lib/nagios/plugins/check_exit_status.pl ' - '-s /etc/init.d/%s status > ' - '/var/lib/nagios/service-check-%s.txt\n' % (svc, - svc) - ) + checkpath = '/var/lib/nagios/service-check-%s.txt' % svc + croncmd = ( + '/usr/local/lib/nagios/plugins/check_exit_status.pl ' + '-s /etc/init.d/%s status' % svc + ) + cron_file = '*/5 * * * * root %s > %s\n' % (croncmd, checkpath) f = open(cronpath, 'w') f.write(cron_file) f.close() nrpe.add_check( shortname=svc, - description='process check {%s}' % unit_name, - check_cmd='check_status_file.py -f ' - '/var/lib/nagios/service-check-%s.txt' % svc, + description='service check {%s}' % unit_name, + check_cmd='check_status_file.py -f %s' % checkpath, ) + if immediate_check: + f = open(checkpath, 'w') + subprocess.call( + croncmd.split(), + stdout=f, + stderr=subprocess.STDOUT + ) + f.close() + os.chmod(checkpath, 0o644) def copy_nrpe_checks(): diff --git a/charmhelpers/contrib/database/mysql.py b/charmhelpers/contrib/database/mysql.py index 39af41e..36e783a 100644 --- a/charmhelpers/contrib/database/mysql.py +++ b/charmhelpers/contrib/database/mysql.py @@ -142,6 +142,13 @@ class MySQLHelper(object): finally: cursor.close() + def flush_priviledges(self): + cursor = self.connection.cursor() + try: + cursor.execute("FLUSH PRIVILEGES") + finally: + cursor.close() + def execute(self, sql): """Execute arbitary SQL against the database.""" cursor = self.connection.cursor() @@ -323,6 +330,7 @@ class MySQLHelper(object): self.create_grant(database, username, remote_ip, password) else: self.create_admin_grant(username, remote_ip, password) + self.flush_priviledges() return password @@ -336,6 +344,21 @@ class PerconaClusterHelper(object): DEFAULT_INNODB_BUFFER_FACTOR = 0.50 DEFAULT_INNODB_BUFFER_SIZE_MAX = 512 * 1024 * 1024 + # Validation and lookups for InnoDB configuration + INNODB_VALID_BUFFERING_VALUES = [ + 'none', + 'inserts', + 'deletes', + 'changes', + 'purges', + 'all' + ] + INNODB_FLUSH_CONFIG_VALUES = { + 'fast': 2, + 'safest': 1, + 'unsafe': 0, + } + def human_to_bytes(self, human): """Convert human readable configuration options to bytes.""" num_re = re.compile('^[0-9]+$') @@ -399,7 +422,18 @@ class PerconaClusterHelper(object): mysql_config['wait_timeout'] = config['wait-timeout'] if 'innodb-flush-log-at-trx-commit' in config: - mysql_config['innodb_flush_log_at_trx_commit'] = config['innodb-flush-log-at-trx-commit'] + mysql_config['innodb_flush_log_at_trx_commit'] = \ + config['innodb-flush-log-at-trx-commit'] + elif 'tuning-level' in config: + mysql_config['innodb_flush_log_at_trx_commit'] = \ + self.INNODB_FLUSH_CONFIG_VALUES.get(config['tuning-level'], 1) + + if ('innodb-change-buffering' in config and + config['innodb-change-buffering'] in self.INNODB_VALID_BUFFERING_VALUES): + mysql_config['innodb_change_buffering'] = config['innodb-change-buffering'] + + if 'innodb-io-capacity' in config: + mysql_config['innodb_io_capacity'] = config['innodb-io-capacity'] # Set a sane default key_buffer size mysql_config['key_buffer'] = self.human_to_bytes('32M') diff --git a/config.yaml b/config.yaml index 66d7bcf..de2d1b3 100644 --- a/config.yaml +++ b/config.yaml @@ -40,6 +40,45 @@ options: memory or 512MB (whichever is lowest) but also can be set to any specific value for the system. Supported suffixes include K/M/G/T. If suffixed with %, one will get that percentage of system total memory allocated. + innodb-change-buffering: + type: string + default: + description: | + Configure whether InnoDB performs change buffering, an optimization + that delays write operations to secondary indexes so that the I/O + operations can be performed sequentially. + + Permitted values include + + none Do not buffer any operations. + inserts Buffer insert operations. + deletes Buffer delete marking operations; strictly speaking, + the writes that mark index records for later deletion + during a purge operation. + changes Buffer inserts and delete-marking operations. + purges Buffer the physical deletion operations that happen + in the background. + all The default. Buffer inserts, delete-marking + operations, and purges. + + For more details https://dev.mysql.com/doc/refman/5.6/en/innodb-parameters.html#sysvar_innodb_change_bufferring + innodb-io-capacity: + type: int + default: + description: | + Configure the InnoDB IO capacity which sets an upper limit on I/O + activity performed by InnoDB background tasks, such as flushing pages + from the buffer pool and merging data from the change buffer. + + This value typically defaults to 200 but can be increased on systems + with fast bus-attached SSD based storage to help the server handle the + background maintenance work associated with a high rate of row changes. + + Alternatively it can be decreased to a minimum of 100 on systems with + low speed 5400 or 7200 rpm spindles, to reduce the proportion of IO + operations being used for background maintenance work. + + For more details https://dev.mysql.com/doc/refman/5.6/en/innodb-parameters.html#sysvar_innodb_io_capacity max-connections: type: int default: 600 @@ -228,3 +267,11 @@ options: implication of this is one can set configuration values that could lead to memory exhaustion during run time as memory is not allocated at startup time. + tuning-level: + default: safest + type: string + description: | + Valid values are 'safest', 'fast', and 'unsafe'. If set to 'safest', all + settings are tuned to have maximum safety at the cost of performance. + 'fast' will turn off most controls, but may lose data on crashes. 'unsafe' + will turn off all protections but this may be OK in clustered deployments. diff --git a/templates/my.cnf b/templates/my.cnf index b0996a7..969f067 100644 --- a/templates/my.cnf +++ b/templates/my.cnf @@ -54,6 +54,20 @@ innodb_file_per_table = 1 innodb_file_per_table = 0 {% endif %} +# This option is driven by via the tuning-level configuration option +# safest = 1 (default) +# fast = 2 +# unsafe = 0 +innodb_flush_log_at_trx_commit = {{ innodb_flush_log_at_trx_commit }} + +{% if innodb_change_buffering -%} +innodb_change_buffering = {{ innodb_change_buffering }} +{% endif %} + +{% if innodb_io_capacity -%} +innodb_io_capacity = {{ innodb_io_capacity }} +{% endif %} + # Node #1 address wsrep_node_address={{ private_address }} diff --git a/templates/mysqld.cnf b/templates/mysqld.cnf index 114133d..d4f999d 100644 --- a/templates/mysqld.cnf +++ b/templates/mysqld.cnf @@ -85,8 +85,22 @@ innodb_file_per_table = 1 innodb_file_per_table = 0 {% endif %} +# This option is driven by via the tuning-level configuration option +# safest = 1 (default) +# fast = 2 +# unsafe = 0 +innodb_flush_log_at_trx_commit = {{ innodb_flush_log_at_trx_commit }} + innodb_buffer_pool_size = {{ innodb_buffer_pool_size }} +{% if innodb_change_buffering -%} +innodb_change_buffering = {{ innodb_change_buffering }} +{% endif %} + +{% if innodb_io_capacity -%} +innodb_io_capacity = {{ innodb_io_capacity }} +{% endif %} + # # * Galera #