Veel systeembeheerders zien het belang van voortdurende afstemming van de databaseconfiguratie over het hoofd. Configuratie-opties worden vaak eenmalig geconfigureerd of afgestemd, tijdens de installatiefase, en worden weggelaten totdat er ongewenste gebeurtenissen plaatsvinden in de databaseservice. Alleen dan zou men meer aandacht besteden aan het opnieuw bezoeken van de configuratie-opties en het afstemmen van de limieten, drempels, buffers, caches, enz., in de drang om de databaseservice opnieuw te herstellen.
Onze focus in deze blogpost is om het controle- en validatieproces van de databaseconfiguratie te automatiseren. Dit is een belangrijk proces omdat configuratie-opties altijd veranderen in de belangrijkste versies. Een ongewijzigd configuratiebestand kan mogelijk verouderde opties hebben die niet langer worden ondersteund door de nieuwere serverversie, wat vaak grote problemen veroorzaakt met de geüpgradede server.
Configuratiebeheertools
Puppet, Ansible, Chef en SaltStack worden het meest gebruikt door DevOps voor configuratiebeheer en automatisering. Met configuratiebeheer kunnen gebruikers de omgeving documenteren, de efficiëntie, beheersbaarheid en reproduceerbaarheid verbeteren en een integraal onderdeel vormen van continue integratie en implementatie. De meeste hulpprogramma's voor configuratiebeheer bieden een catalogus met modules en opslagplaatsen waaraan anderen kunnen bijdragen, wat de leercurve voor de communitygebruiker vereenvoudigt om zich aan de technologie aan te passen.
Hoewel configuratiebeheertools meestal worden gebruikt om de implementatie en installatie te automatiseren, kunnen we ook configuratiecontroles en handhaving uitvoeren in een gecentraliseerde push-outbenadering. Elk van deze tools heeft zijn eigen manier om een configuratiebestand te modelleren. Wat betreft Puppet, het sjabloonbestand dat gewoonlijk wordt achtervoegd met ".erb" en daarin kunnen we de configuratie-opties definiëren samen met vooraf geformuleerde waarden.
Het volgende voorbeeld toont een sjabloonbestand voor MySQL-configuratie:
[mysqld]
thread_concurrency = <%= processorcount.to_i * 2 %>
# Replication
log-bin = /var/lib/mysql/mysql-bin.log
log-bin-index = /var/lib/mysql/mysql-bin.index
binlog_format = mixed
server-id = <%= @mysql_server_id or 1 %>
# InnoDB
innodb_buffer_pool_size = <%= (memorysizeinbytes.to_i / 2 / 1024 / 1024).to_i -%>M
innodb_log_file_size = <%= ((memorysizeinbytes.to_i / 2 / 1024 / 1024) * 0.25).to_i -%>M
Zoals hierboven weergegeven, kan de configuratiewaarde een vaste waarde zijn of dynamisch worden berekend. Daarom kan het eindresultaat verschillen volgens de hardwarespecificatie van de doelhost met andere vooraf gedefinieerde variabelen. In het Puppet-definitiebestand kunnen we onze configuratiesjabloon als volgt pushen:
# Apply our custom template
file { '/etc/mysql/conf.d/my-custom-config.cnf':
ensure => file,
content => template('mysql/my-custom-config.cnf.erb')
}
Anders dan sjablonen, kunnen we de configuratiewaarden ook rechtstreeks vanuit het definitiebestand pushen. Het volgende is een voorbeeld van een Puppet-definitie voor MariaDB 10.5-configuratie met behulp van de Puppet MySQL-module:
# MariaDB configuration
class {'::mysql::server':
package_name => 'mariadb-server',
service_name => 'mariadb',
root_password => 't5[sb^D[+rt8bBYu',
manage_config_file => true,
override_options => {
mysqld => {
'bind_address' => '127.0.0.1',
'max_connections' => '500',
'log_error' => '/var/log/mysql/mariadb.log',
'pid_file' => '/var/run/mysqld/mysqld.pid',
},
mysqld_safe => {
'log_error' => '/var/log/mysql/mariadb.log',
},
}
}
Het bovenstaande voorbeeld laat zien dat we manage_config_file => true met override_options gebruikten om onze configuratieregels te structureren, die later door Puppet naar buiten zullen worden geduwd. Elke wijziging aan het manifestbestand geeft alleen de inhoud van het MySQL-doelconfiguratiebestand weer. Deze module laadt de configuratie niet in runtime en start de MySQL-service ook niet opnieuw nadat de wijzigingen in het configuratiebestand zijn doorgevoerd. Het is de verantwoordelijkheid van de SysAdmin om de service opnieuw te starten om de wijzigingen te activeren.
Voor Puppet en Chef:controleer de uitvoer van het agentlogboek om te zien of de configuratie-opties zijn gecorrigeerd. Voor Ansible hoeft u alleen maar naar de foutopsporingsoutput te kijken om te zien of de felicitaties met succes zijn bijgewerkt. Door configuratiebeheertools te gebruiken, kunt u configuratiecontroles automatiseren en een gecentraliseerde configuratiebenadering afdwingen.
MySQL-shell
Een gezondheidscheck is belangrijk voordat u een upgrade uitvoert. MySQL Shell heeft een zeer coole functie die bedoeld is om een reeks tests uit te voeren om te controleren of uw bestaande installatie veilig is om te upgraden naar MySQL 8.0, genaamd Upgrade Checker Utility. U kunt enorm veel tijd besparen bij het voorbereiden van een upgrade. Een grote upgrade, vooral naar MySQL 8.0, introduceert en deprecieert veel configuratie-opties en heeft daarom een groot risico op incompatibiliteit na de upgrade.
Deze tool is speciaal ontworpen voor MySQL (inclusief Percona Server), vooral als je een grote upgrade wilt uitvoeren van MySQL 5.7 naar MySQL 8.0. Om dit hulpprogramma aan te roepen, maakt u verbinding met MySQL Shell en specificeert u als rootgebruiker de inloggegevens, de doelversie en het configuratiebestand:
$ mysqlsh
mysql> util.checkForServerUpgrade('[email protected]:3306', {"password":"p4ssw0rd", "targetVersion":"8.0.11", "configPath":"/etc/my.cnf"})
Onderaan het rapport vindt u de belangrijkste samenvatting:
Errors: 7
Warnings: 36
Notices: 0
7 errors were found. Please correct these issues before upgrading to avoid compatibility issues.
Focus eerst op het oplossen van alle fouten, want dit gaat grote problemen veroorzaken na de upgrade als er geen actie wordt ondernomen. Kijk terug naar het gegenereerde rapport en vind alle problemen met de bewoording "Error:" inline, bijvoorbeeld:
15) Removed system variables
Error: Following system variables that were detected as being used will be
removed. Please update your system to not rely on them before the upgrade.
More information: https://dev.mysql.com/doc/refman/8.0/en/added-deprecated-removed.html#optvars-removed
log_builtin_as_identified_by_password - is set and will be removed
show_compatibility_56 - is set and will be removed
Zodra alle fouten zijn verholpen, probeert u de waarschuwingen zoveel mogelijk te verminderen. De waarschuwingen hebben meestal geen invloed op de betrouwbaarheid van de MySQL-server, maar kunnen mogelijk de prestaties of het gewijzigde gedrag verslechteren dan vroeger. Bekijk bijvoorbeeld de volgende waarschuwingen:
13) System variables with new default values
Warning: Following system variables that are not defined in your
configuration file will have new default values. Please review if you rely on
their current values and if so define them before performing upgrade.
More information:
https://mysqlserverteam.com/new-defaults-in-mysql-8-0/
back_log - default value will change
character_set_server - default value will change from latin1 to utf8mb4
collation_server - default value will change from latin1_swedish_ci to
utf8mb4_0900_ai_ci
event_scheduler - default value will change from OFF to ON
explicit_defaults_for_timestamp - default value will change from OFF to ON
innodb_autoinc_lock_mode - default value will change from 1 (consecutive) to
2 (interleaved)
innodb_flush_method - default value will change from NULL to fsync (Unix),
unbuffered (Windows)
innodb_flush_neighbors - default value will change from 1 (enable) to 0
(disable)
innodb_max_dirty_pages_pct - default value will change from 75 (%) 90 (%)
innodb_max_dirty_pages_pct_lwm - default value will change from_0 (%) to 10
(%)
innodb_undo_log_truncate - default value will change from OFF to ON
innodb_undo_tablespaces - default value will change from 0 to 2
log_error_verbosity - default value will change from 3 (Notes) to 2 (Warning)
max_allowed_packet - default value will change from 4194304 (4MB) to 67108864
(64MB)
max_error_count - default value will change from 64 to 1024
optimizer_trace_max_mem_size - default value will change from 16KB to 1MB
performance_schema_consumer_events_transactions_current - default value will
change from OFF to ON
performance_schema_consumer_events_transactions_history - default value will
change from OFF to ON
slave_rows_search_algorithms - default value will change from 'INDEX_SCAN,
TABLE_SCAN' to 'INDEX_SCAN, HASH_SCAN'
table_open_cache - default value will change from 2000 to 4000
transaction_write_set_extraction - default value will change from OFF to
XXHASH64
Upgrade Checker Utility biedt een kritisch overzicht van wat we kunnen verwachten en voorkomt dat we voor een enorme verrassing komen te staan na de upgrade.
ClusterControl-adviseurs
ClusterControl heeft een aantal interne miniprogramma's genaamd Advisors, waar je een klein programma schrijft dat leeft en draait binnen de structuur van de ClusterControl-objecten. Je kunt het zien als een geplande functie die een script uitvoert dat is gemaakt in Developer Studio en een resultaat produceert met status, advies en rechtvaardiging. Hierdoor kunnen gebruikers de functionaliteit van ClusterControl eenvoudig uitbreiden door aangepaste adviseurs te maken die on-demand of volgens een schema kunnen worden uitgevoerd.
De volgende schermafbeelding toont een voorbeeld van InnoDB Advisors genaamd innodb_log_file_size check, nadat deze is geactiveerd en gepland in ClusterControl:
Het bovenstaande resultaat is te vinden onder ClusterControl -> Performance -> Advisors. Het toont voor elke Adviseur de status van de adviseur, database-instantie, motivering en advies. Ook is er informatie over de planning en de laatste uitvoeringstijd. De adviseur kan ook on-demand worden uitgevoerd door op de knop "Compileren en uitvoeren" onder de Developer Studio te klikken.
De bovenstaande adviseurs bevatten de volgende code, geschreven met behulp van ClusterControl Domain-Specific Language (DSL) die vrij veel lijkt op JavaScript:
#include "common/mysql_helper.js"
#include "cmon/graph.h"
var DESCRIPTION="This advisor calculates the InnoDB log growth per hour and"
" compares it with the innodb_log_file_size configured on the host and"
" notifies you if the InnoDB log growth is higher than what is configured, which is important to avoid IO spikes during flushing.";
var TITLE="Innodb_log_file_size check";
var MINUTES = 20;
function main()
{
var hosts = cluster::mySqlNodes();
var advisorMap = {};
for (idx = 0; idx < hosts.size(); ++idx)
{
host = hosts[idx];
map = host.toMap();
connected = map["connected"];
var advice = new CmonAdvice();
print(" ");
print(host);
print("==========================");
if (!connected)
{
print("Not connected");
continue;
}
if (checkPrecond(host))
{
var configured_logfile_sz = host.sqlSystemVariable("innodb_log_file_size");
var configured_logfile_grps = host.sqlSystemVariable("innodb_log_files_in_group");
if (configured_logfile_sz.isError() || configured_logfile_grps.isError())
{
justification = "";
msg = "Not enough data to calculate";
advice.setTitle(TITLE);
advice.setJustification("");
advice.setAdvice(msg);
advice.setHost(host);
advice.setSeverity(Ok);
advisorMap[idx]= advice;
continue;
}
var endTime = CmonDateTime::currentDateTime();
var startTime = endTime - MINUTES * 60 /*seconds*/;
var stats = host.sqlStats(startTime, endTime);
var array = stats.toArray("created,interval,INNODB_LSN_CURRENT");
if(array[2,0] === #N/A || array[2,0] == "")
{
/* Not all vendors have INNODB_LSN_CURRENT*/
advice.setTitle(TITLE);
advice.setJustification("INNODB_LSN_CURRENT does not exists in"
" this MySQL release.");
advice.setAdvice("Nothing to do.");
advice.setHost(host);
advice.setSeverity(Ok);
advisorMap[idx]= advice;
continue;
}
var firstLSN = array[2,0].toULongLong();
var latestLSN = array[2,array.columns()-1].toULongLong();
var intervalSecs = endTime.toULongLong() - startTime.toULongLong();
var logGrowthPerHourMB = ceiling((latestLSN - firstLSN) * 3600 / 1024/1024 / intervalSecs / configured_logfile_grps);
var logConfiguredMB = configured_logfile_sz/1024/1024;
if (logGrowthPerHourMB > logConfiguredMB)
{
justification = "Innodb is producing " + logGrowthPerHourMB + "MB/hour, and it greater than"
" the configured innodb log file size " + logConfiguredMB + "MB."
" You should set innodb_log_file_size to a value greater than " +
logGrowthPerHourMB + "MB. To change"
" it you must stop the MySQL Server and remove the existing ib_logfileX,"
" and start the server again. Check the MySQL reference manual for max/min values. "
"https://dev.mysql.com/doc/refman/5.6/en/innodb-parameters.html#sysvar_innodb_log_file_size";
msg = "You are recommended to increase the innodb_log_file_size to avoid i/o spikes"
" during flushing.";
advice.setSeverity(Warning);
}
else
{
justification = "Innodb_log_file_size is set to " + logConfiguredMB +
"MB and is greater than the log produced per hour: " +
logGrowthPerHourMB + "MB.";
msg = "Innodb_log_file_size is sized sufficiently.";
advice.setSeverity(Ok);
}
}
else
{
justification = "Server uptime and load is too low.";
msg = "Not enough data to calculate";
advice.setSeverity(0);
}
advice.setHost(host);
advice.setTitle(TITLE);
advice.setJustification(justification);
advice.setAdvice(msg);
advisorMap[idx]= advice;
print(advice.toString("%E"));
}
return advisorMap;
}
ClusterControl biedt een kant-en-klare geïntegreerde ontwikkelomgeving (IDE) genaamd Developer Studio (toegankelijk onder Beheren -> Developer Studio) om de Advisor te schrijven, compileren, opslaan, debuggen en plannen:
Met Developer Studio en Advisors hebben gebruikers geen limiet bij het uitbreiden van de monitoring- en beheerfuncties van ClusterControl. Het is letterlijk de perfecte tool om de configuratiecontrole te automatiseren voor al uw open-source databasesoftware zoals MySQL, MariaDB, PostgreSQL en MongoDB, evenals de load balancers zoals HAProxy, ProxySQL, MaxScale en PgBouncer. U kunt zelfs een adviseur schrijven om gebruik te maken van de MySQL Shell Upgrade Checker Utility, zoals weergegeven in het vorige hoofdstuk.
Laatste gedachten
Configuratiecontrole en afstemming zijn belangrijke onderdelen van de DBA- en SysAdmin-routine om ervoor te zorgen dat kritieke systemen zoals database en reverse proxy's altijd relevant en optimaal zijn naarmate uw werklast groeit.