Benutzer-Werkzeuge

Webseiten-Werkzeuge


mysql

Dies ist eine alte Version des Dokuments!


Inhaltsverzeichnis

MySQL

Aussprache des Namens: Die offizielle Aussprache ist Mei-es-kju-ell.

Seit MySQL 3.23 (Januar 2001) gibt es eine eingebaute Replikation.
Seit MySQL 5.5 (03. Dezember 2010) unterstützt die Standard-Speicherengine (InnoDB) erst Transaktionen.

Welche MySQL-Variante ist installiert?
> dpkg -l | grep -Ei 'mysql|mariadb|percona|xtradb'

Ab Version 8.0 ist MySQL nicht mehr abwärtskompatibel – weder zu älteren MySQL-Versionen noch zu MariaDB. MariaDB möchte sich von MySQL zukünftig vor allem durch Flexibilität abgrenzen. Anwendern steht neben den von MySQL unterstützten Standard-Engines eine stetig wachsende Anzahl alternativer Datenbank-Engines für spezielle Anwendungsfälle zur Verfügung.

> echo "SHOW VARIABLES WHERE Variable_name LIKE ('version%');" | mysql -t
+-------------------------+-------------------------------------------------------------------------------------+
| Variable_name           | Value                                                                               |
+-------------------------+-------------------------------------------------------------------------------------+
| version                 | 8.0.26-16.1                                                                         |
| version_comment         | Percona XtraDB Cluster (GPL), Release rel16, Revision b141904, WSREP version 26.4.3 |
| version_compile_machine | x86_64                                                                              |
| version_compile_os      | Linux                                                                               |
| version_compile_zlib    | 1.2.11                                                                              |
| version_suffix          | .1                                                                                  |
+-------------------------+-------------------------------------------------------------------------------------+
ignore-db-dir        = lost+found

Maximale Anzahl der bisher gleichzeitigen Verbindungen (Galera/WSREP)

<hidden ~/bin/Max_used_connections.sh>

~/bin/Max_used_connections.sh
#!/bin/bash
 
for S in $(ls /var/run/mysqld/mysqld*.sock)
do
	echo "SHOW STATUS;" | mysql --socket=${S} | grep -Ei 'wsrep_incoming_addresses|Max_used_connections[^_]' | awk '{print $2}' | tr -s '\n' '\t'
	echo
done

</hidden>

# /root/bin/Max_used_connections.sh
4	db01:3316,db02:3316,db03:3316
1084	db01:3326,db02:3326,db03:3326

RAM-Verbrauch abschätzen

> touch ~/bin/MySQL-RAM.sh
> chmod 0755 ~/bin/MySQL-RAM.sh
> vim ~/bin/MySQL-RAM.sh

<hidden ~/bin/MySQL-RAM.sh>

~/bin/MySQL-RAM.sh
#!/bin/bash
 
#VERSION="v2024061200"		# erstellt
VERSION="v2024061800"		# verbessert
 
if [ x = "x${1}" ] ; then
	STECKER="-S /var/run/mysqld/mysqld.sock"
else
	STECKER="-S /var/run/mysqld/mysqld_${1}.sock"
fi
 
# mysqlshow --defaults-file=~/.my.cnf --socket=/var/run/mysqld/mysqld.sock
MYSQL_AUSGABE="$(echo "SHOW VARIABLES;" | mysql -N ${STECKER} | grep -Ei '^key_buffer_size|^read_buffer_size|^sort_buffer_size|^max_connections')"
echo "${MYSQL_AUSGABE}" | sed 's/.*/    &/'
echo "# key_buffer_size + (read_buffer_size + sort_buffer_size) * max_connections = K bytes of memory"
KEY_BUFFER_SIZE="$(echo "${MYSQL_AUSGABE}" | awk '/^key_buffer_size/{print $2}')"
READ_BUFFER_SIZE="$(echo "${MYSQL_AUSGABE}" | awk '/^read_buffer_size/{print $2}')"
SORT_BUFFER_SIZE="$(echo "${MYSQL_AUSGABE}" | awk '/^sort_buffer_size/{print $2}')"
MAX_CONNECTIONS="$(echo "${MYSQL_AUSGABE}" | awk '/^max_connections/{print $2}')"
echo "
SHOW STATUS;
SHOW VARIABLES;
" | mysql -N ${STECKER} | grep -Ei 'Max_used_connections|^max_allowed_packet'
echo
echo "SELECT * FROM sys.memory_global_total \G;" | mysql -t ${STECKER} | grep -F total_allocated
echo "${KEY_BUFFER_SIZE} ${READ_BUFFER_SIZE} ${SORT_BUFFER_SIZE} ${MAX_CONNECTIONS}" | awk '{printf "MySQL-RAM-Bedarf: ca. %.0f MiB\n", ($1 + ($2 + $3) * $4) / 1024}'
echo
free -m

</hidden>

> ~/bin/MySQL-RAM.sh
    key_buffer_size	4194304
    max_connections	50
    read_buffer_size	65536
    sort_buffer_size	131072
# key_buffer_size + (read_buffer_size + sort_buffer_size) * max_connections = K bytes of memory
Max_used_connections	31
Max_used_connections_time	2024-06-12 00:25:12
max_allowed_packet	33554432
 
MySQL-RAM-Bedarf: ca. 13696 MiB
 
              total        used        free      shared  buff/cache   available
Mem:          15997        9797         157           0        6042        5869
Swap:             0           0           0

verschiedene MySQL-Cluster-Varianten

  • Die MySQL-Shell enthält die MySQL AdminAPI, auf die über die globale Variable dba und die zugehörigen Methoden zugegriffen wird. MySQL-Shell bietet neben einem nativen SQL-Modus zwei Skriptsprachenmodi, JavaScript und Python. Wenn MySQL-Shell gestartet wird, befindet es sich standardmäßig im JavaScript-Modus. Wechseln Sie den Modus, indem Sie \js für den JavaScript-Modus und \py für den Python-Modus ausgeben.
    • InnoDB ReplicaSet - Asynchrone Replikation, die auf GTID basiert
    • Group Replication - Semisynchrone Replikation
      • Im Multi-Primär-Modus können langsamere Mitglieder auch einen übermäßigen Rückstand an zu zertifizierenden und anzuwendenden Transaktionen aufbauen, … → Das bedeutet, es ist keine synchrone Replikationstechnik!
    • InnoDB Cluster - Back-End der Group Replication
    • MySQL Router - übernimmt die Aufgabe, die auch ProxySQL erledigt, nur speziell für "Group Replication"
  • Percona XtraDB Cluster - Synchrone Replikation

Asynchrone MySQL-Replikation

Synchrone MySQL-Replikation

verschiedenes

Kurtzübersicht SQL:

  • (Lese-)Rechte auf alle Tabellen einer DB erteilen: GRANT SELECT ON db.* TO fritz; FLUSH PRIVILEGES;
  • Tabelle umbenennen bzw. verschieben: RENAME TABLE db_alt.tabelle_alt TO db_neu.tabelle_neu;
  • alle Tabellenpartitionen anzeigen: SELECT TABLE_SCHEMA,TABLE_NAME,PARTITION_NAME FROM INFORMATION_SCHEMA.PARTITIONS WHERE PARTITION_DESCRIPTION IS NOT NULL;
  • Inhalt einer Partition zählen: SELECT COUNT(*) FROM db.tabelle PARTITION (name_der_partition);
  • Datensatz eintragen: INSERT INTO db.tabelle SELECT * FROM db.tabelle WHERE feld01='wert';
  • Datensatz ändern: UPDATE db.tabelle SET feld02='wert01' WHERE feld01='wert';
  • Datensatz löschen: DELETE FROM db.tabelle WHERE feld01='wert';
  • Root-Passwort ändern (vor MySQL 8.0): UPDATE mysql.user SET authentication_string=PASSWORD('geheim') WHERE User='root';
  • Root-Passwort ändern (ab MySQL 8.0): ALTER USER root IDENTIFIED BY 'geheim'; FLUSH PRIVILEGES;

einen Benutzer mit Passwort in einer anderen DB eintragen, ohne das Passwort kennen zu müssen:

# echo "SELECT user,authentication_string FROM mysql.user;" | mysql -hdbserver -P3306 -N | awk '{print "CREATE USER",$1,"; UPDATE mysql.user SET authentication_string=\""$2"\" WHERE user=\""$1"\";"}'
...
CREATE USER fritz;
CREATE USER fritz IDENTIFIED BY 'Passwort'; FLUSH PRIVILEGES;
CREATE USER fritz IDENTIFIED WITH mysql_native_password AS '*EC567F88BA2EC345EAE597C24C33B0364D5DBA60';

ALTER USER fritz IDENTIFIED BY 'Passwort'; FLUSH PRIVILEGES;
UPDATE mysql.user SET authentication_string="*EC567F88BA2EC345EAE597C24C33B0364D5DBA60" WHERE user="fritz";
FLUSH PRIVILEGES;
...

Aus diesen CREATE USER-Kommandos sucht man sich dann die relevanten aus und gibt sie in der neuen DB ein.

> echo "SHOW DATABASES LIKE 'mysql';" | mysql -t
+------------------+
| Database (mysql) |
+------------------+
| mysql            |
+------------------+
> echo "USE mysql; SHOW TABLES LIKE 'user';" | mysql -t
+------------------------+
| Tables_in_mysql (user) |
+------------------------+
| user                   |
+------------------------+

MySQL mit Replikation

Variablen ausgeben

@@ zeigt auf global definierte Variablen

@ zeigt auf für die Session definierte Variablen

SELECT @@server_id
SELECT CONCAT(@@server_id, UUID());
SHOW VARIABLES LIKE 'server_id';
SHOW VARIABLES WHERE Variable_name IN ('server_id');

nach Datum selektiert ausgeben

  • aktueller Zeitstempel: NOW()2020-03-25 17:31:46
  • aktuelles/heutiges Datum: DATE(NOW())2020-03-25
  • heutiges Datum: DATE(NOW() - INTERVAL 0 DAY)2020-03-25
  • gestriges Datum: DATE(NOW() - INTERVAL 1 DAY)2020-03-24
  • Datum von Vorgestern: DATE(NOW() - INTERVAL 2 DAY)2020-03-23

die 10 ältesten Einträge von Gestern, absteigend sortiert:

SELECT zeitstempel
FROM datenbank.tabelle
WHERE zeitstempel < DATE(NOW() - INTERVAL 0 DAY)
AND zeitstempel > DATE(NOW() - INTERVAL 1 DAY)
ORDER BY zeitstempel
ASC
LIMIT 10;

die 10 jüngsten Einträge von Gestern, aufsteigend sortiert:

SELECT zeitstempel
FROM datenbank.tabelle
WHERE zeitstempel < DATE(NOW() - INTERVAL 0 DAY)
AND zeitstempel > DATE(NOW() - INTERVAL 1 DAY)
ORDER BY zeitstempel
DESC
LIMIT 10;

die 10 ältesten Einträge von Vorgestern, absteigend sortiert:

SELECT zeitstempel
FROM datenbank.tabelle
WHERE zeitstempel < DATE(NOW() - INTERVAL 1 DAY)
AND zeitstempel > DATE(NOW() - INTERVAL 2 DAY)
ORDER BY zeitstempel
ASC
LIMIT 10;

VIEWs zeigen

alle VIEWs in der DB zeigen:

> echo "SELECT * FROM VIEWS \G;" | mysql -t information_schema

alle VIEWs in einer bestimmten DB zeigen:

> echo "SHOW FULL TABLES IN DatenBankName WHERE table_type = 'VIEW';" | mysql -t

nur eine mit Details anzeigen (die Platzhalter in den eckigen Klammern, werden bei der Ausgabe von "SELECT * FROM VIEWS" mit Namen angezeigt):

> echo "SHOW CREATE VIEW [TABLE_NAME] \G;" | mysql -t [TABLE_SCHEMA]
> echo "SHOW CREATE VIEW viewname \G;" | mysql -t datenbankname

Dirty Pages

> echo "SHOW VARIABLES LIKE 'innodb_max_dirty_pages_pct'; SHOW GLOBAL STATUS LIKE '%dirty%';" | mysql -t
+----------------------------+-----------+
| Variable_name              | Value     |
+----------------------------+-----------+
| innodb_max_dirty_pages_pct | 75.000000 |
+----------------------------+-----------+
+--------------------------------+---------+
| Variable_name                  | Value   |
+--------------------------------+---------+
| Innodb_buffer_pool_pages_dirty | 115     |
| Innodb_buffer_pool_bytes_dirty | 1884160 |
+--------------------------------+---------+

Stellt man "innodb_max_dirty_pages_pct" auf "0", dann werden beim DB anhalten immer alle Daten komplett in die Tabellen geschrieben. Das hat zur Folge, dass die DB mehr Zeit zum anhalten benötigt.

Eine Tabelle stückchenweise durchlaufen

/root/bin/Tabelle_stückchenweise durchlaufen.sh
#!/bin/bash
 
DB="test_db"
TAB="test_tab"
 
VON="0"
ANZAHL="1000"
#NR="16525955"
NR="$(echo "SELECT COUNT(*) FROM ${DB}.${TAB};" | mysql -N)"
while (( "${VON}" <= "${NR}" ))
do
        # hier wird die Größe der Datensätze aus einer Spalte gemessen und in eine andere Tabelle geschrieben
        echo "INSERT INTO ${DB}.data_length_${TAB}_test SELECT LENGTH(ENTRYDATA), ID FROM ${DB}.${TAB} LIMIT ${VON},${ANZAHL};" | mysql
        VON="$(echo "${VON} ${ANZAHL}" | awk '{print $1 + $2 + 1}')"
done

Überwachung

/root/bin/check_debian_db.sh
#!/bin/bash
 
#==============================================================================#
#
# DB-Check
#
#------------------------------------------------------------------------------#
#
# /etc/mysql/debian.cnf
#
# mysqladmin --defaults-file=/etc/mysql/debian.cnf ping
# mysqld is alive
#
#==============================================================================#
 
DB_STATUS=$(mysqladmin --defaults-file=/etc/mysql/debian.cnf ping);
 
#echo "
#DB_STATUS='${DB_STATUS}'
#"
 
if [ "${DB_STATUS}" = "mysqld is alive" ]
then
        # An
        exit 0;
else
        # Aus
        exit 1;
fi

Benchmark

Tabelle per SQL in eine andere Datenbank kopieren

http://blog.mixable.de/mysql-tabellen-in-andere-datenbank-kopieren/

> CREATE TABLE db2.newTable LIKE db1.oldTable
> ALTER  TABLE db2.newTable DISABLE KEYS

alle Tabellen:

> INSERT INTO  db2.newTable SELECT * FROM db1.oldTable

ausgewählte Spalten:

> INSERT INTO  db2.newTable (sp3,sp4,sp7) SELECT sp3,sp4,sp7 FROM db1.oldTable
> ALTER  TABLE db2.newTable ENABLE KEYS

aus einer Tabelle (oldTable) bestimmte Datensätze in eine andere Tabelle (newTable) überschreiben (löschen+kopieren):

> for id in 1 2 3 4 5 6 7 8 9 ; do echo "DELETE FROM newTable WHERE id='${id}'; INSERT INTO newTable SELECT * FROM oldTable WHERE id='${id}';" | mysql -N db ; done

InnoDB Status

> SHOW ENGINE INNODB STATUS;

Aus dieser Ausgabe kann man folgende Informationen gewinnen:

  • BACKGROUND THREAD
  • SEMAPHORES
  • LATEST DETECTED DEADLOCK
  • TRANSACTIONS
  • FILE I/O
  • INSERT BUFFER AND ADAPTIVE HASH INDEX
  • LOG
  • BUFFER POOL AND MEMORY
  • INDIVIDUAL BUFFER POOL INFO
  • ROW OPERATIONS

MySQL-Sicherungsmethoden

Für dieses Beispiel wurde eine VM mit zwei CPU-Kernen und einem MySQL-Volumen (LVM) von ca. 280GiB größe verwendet. Die MySQL-Daten in dem Verzeichnis bzw. auf dem Volumen belegen, inklusive BIN-LOGs, ca. 99 GiB. Alle folgenden Angaben beziehen sich auf diese Werte.

Im ersten anlauf wurde ein Verzeichnis per SSHFS eingebunden und dort ein (mit gzip gepackter) Dump abgelegt.

Es wurde dieses Kommando dafür eingesetzt (mit Bandbreitenbegrenzung auf 3 MiB/s: mit "pv"):

  • mysqldump -AREc --opt --triggers | gzip -9 | pv -q -L 3m > mysqldump.tar.gzca. 1,9 Stunden
    • unkomprimierte Dump-Größe: ca. 33 GiB
    • komprimierte Dump-Größe: ca. 20 GiB

Weiterhin gibt es die Möglichkeit ein LVM-SnapShot als Sicherung zu verwendet, dabei wären dann auch die BIN-LOG's gesichert.

Ein experimenteller Sicherungstest hat folgende Messwerte ergeben:

  • tar cvf - /etc/mysql /var/lib/mysql | bzip2 -9 > mysqlbackup.tar.bz2ca. 10,5 Stunden
    • unkomprimierte Daten-Größe: ca. 99 GiB
    • Archiv-Größe: 53,5 GiB
  • 7za a -sfx mysqlbackup_-_ELF_LSB_7z-sfx.exe /etc/mysql /var/lib/mysqlca. 7 Stunden
    • unkomprimierte Daten-Größe: ca. 99 GiB
    • Archiv-Größe: 13,5 GiB

Daraus geht eindeutig hervor, dass in diesem Beispiel das packen mit 7-Zip deutlich effizienter ist als das packen Einsatz von BZip2.

passwortlosen Login

~/.my.cnf
[client]
host     = localhost
user     = root
password = geheim
socket   = /var/run/mysqld/mysqld.sock

speziell bei Debian kann man das (als "root") auch so machen:

# ln -s /etc/mysql/debian.cnf ~/.my.cnf
meine_zugangsdaten.cnf
[client]
user     = root
password = ganzgeheim
socket   = /var/run/mysqld/mysqld.sock

Das kann man so machen, zu beachten ist, dass die Option --defaults-file= die erste sein muss:

> mysqlshow --defaults-file=/etc/mysql/meine_zugangsdaten.cnf -t -hdbrechner
> mysqlshow --defaults-file=/home/ich/.my_dbprivat.cnf -t -hdbrechner
> mysqlshow --defaults-file=/etc/mysql/debian.cnf -t -hdbrechner

Allgemeines

sonst liest MySQL die vorgesehene Konfiguration mein Start nicht ein:

# chmod 0644 /etc/mysql/my.cnf

Ein klassischer MySQL_5-Cluster orientiert sich an der Variablen "server_id", die auf allen Knoten unterschiedlich sein muss!

> echo "SELECT @@server_id;" | mysql -t
+-------------+
| @@server_id |
+-------------+
|        1002 |
+-------------+

oder so

> echo "SHOW VARIABLES LIKE 'server_id';" | mysql -t
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| server_id     | 1002  |
+---------------+-------+

Ein Galera-Cluster orientiert sich an der Variablen "wsrep_cluster_name", die auf allen Knoten gleich sein muss!

> echo "SHOW VARIABLES WHERE Variable_name IN ('wsrep_cluster_name');" | mysql -t
+--------------------+-------------+
| Variable_name      | Value       |
+--------------------+-------------+
| wsrep_cluster_name | meincluster |
+--------------------+-------------+

Hinweis für die Nutzung von GaleraEs dürfen in den Datenbanken nur InnoDB-Tabellen und keine MyISAM-Tabelle verwendet werden! Überprüfen kann man das mit diesem Kommando:

mysqlshow | grep -E '^[|]' | grep -Ev 'Databases|information_schema|performance_schema|mysql' | awk '{print $2}' | while read DB;do mysqlshow -i ${DB} | grep -E '^[|]' | awk '{print $2,$4}' | grep -Eiv 'InnoDB|_view|Name Engine' | sed "s/.*/${DB}.&/";done

eine Tabelle in eine Datei speichern und aus einer Datei wiederherstellen

aus Sicherheitsgründen darf MySQL nur in ein bestimmtes Verzeichnis schreiben und aus ihm lesen:

> echo "SHOW VARIABLES LIKE 'secure_file_priv';" | mysql -B -N | awk '{print $2}'

so wird der Inhalt einer Tabelle in eine Datei geschrieben:

> echo "SELECT * INTO OUTFILE '/var/lib/mysql-files/tabelle.sql' FIELDS TERMINATED BY '|' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n' FROM datenbank.tabelle;" | mysql

so wird der Inhalt aus einer Datei in eine Tabelle geschrieben:

> echo "LOAD DATA INFILE '/var/lib/mysql-files/tabelle.sql' REPLACE INTO TABLE datenbank.tabelle FIELDS TERMINATED BY '|' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n';" | mysql -f

Hierbei muss man auf die Feldtrennzeichen (in diesem Beispiel '|') achten, diese dürfen nicht in der Tabelle vorkommen.

bekannte Fehler und ihre Lösungen

Too many connections

zuviele relay log's

damit die Relay-Logs abgearbeitet werden, muss der SLAVE-Prozess (mindestens der SQL_THREAD) laufen und dann ein FLUSH für die Relay-Logs abgesendet werden:

> echo "STOP SLAVE;" | mysql
> echo "START SLAVE SQL_THREAD;" | mysql
> echo "FLUSH RELAY LOGS;" | mysql

danach:

> echo "START SLAVE;" | mysql

Repairing The Replication: skip the invalid SQL query

> echo "STOP SLAVE;" | mysql
> echo "SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;" | mysql
> echo "START SLAVE;" | mysql

SQL Error (2027): Malformed packet

This error only occurs if the result set is more than a certain number of rows (using LIMIT 14561 rows works, 14562 gives this error).

Oft tritt dieser Fehler auf, wenn CSV-Dateien importiert werden, die unsauber formatiert sind.

arbeiten mit TEMPORARY TABLE

In diesem Beispiel haben wir in einer Datenbank (testdatenbank) zwei Tabellen, aus denen ganz bestimmte Datensätze mit den gleichen IDs gelöscht werden sollen. Die Bedingung lautet, dass die Datensätze von vor dem 2021-01-29 sein sollen, keinen Datumseintrag haben sollen, der Status 'successful' oder 'error' lauten soll und zu einer aus einer Reihe von Kategorien gehören soll.

Zuerst wird mit USE die DB geöffnet, dann wird im ersten Block eine "TEMPORARY TABLE" angelegt (diese verschwindet automatisch, wenn die DB-Verbindung wieder getrennt wird. Im mittleren Block werden die benötigten IDs ausgelesen und in die "TEMPORARY TABLE" geschrieben. Und im letzten Block werden innerhalb einer Transaktion alle Datensätze aus beiden Tabellen gelöscht, die einer der IDs aus der "TEMPORARY TABLE" entsprechen.

beispiel_mit_temporary_table.sql
USE testdatenbank;
 
CREATE TEMPORARY TABLE temp_tabelle(
    id INT PRIMARY KEY
);
 
INSERT INTO temp_tabelle
SELECT id
        FROM test_tabelle_1
        WHERE (startDate < '2021-01-29 00:00:00' OR startDate IS NULL)
        AND state IN ('successful','error')
        AND kategorie IN (73,4,5,6,10,125,126,75,41,59,60,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,123,124,128,134,135);
;
 
START TRANSACTION;
        DELETE FROM test_tabelle_1 WHERE id IN (SELECT id FROM temp_tabelle);
        DELETE FROM test_tabelle_2 WHERE id IN (SELECT id FROM temp_tabelle);
COMMIT;

Start mit MySQL

sollte es Fehlermeldungen beim Start geben, dann kann oft eines dieser Kommandos helfen:

> mysqlcheck -Ag --auto-repair
> mysql_upgrade --force

Ab MySQL 8.0:

> mysql_upgrade 
The mysql_upgrade client is now deprecated. The actions executed by the upgrade client are now done by the server.
To upgrade, please start the new MySQL binary with the older data directory. Repairing user tables is done automatically.
Restart is not required after upgrade.
The upgrade process automatically starts on running a new MySQL binary with an older data directory.
To avoid accidental upgrades, please use the --upgrade=NONE option with the MySQL binary.
The option --upgrade=FORCE is also provided to run the server upgrade sequence on demand.
It may be possible that the server upgrade fails due to a number of reasons.
In that case, the upgrade sequence will run again during the next MySQL server start.
If the server upgrade fails repeatedly, the server can be started with the --upgrade=MINIMAL option
to start the server without executing the upgrade sequence, thus allowing users to manually rectify the problem.

die Strucktur (das Schema) aller Datenbanken schreibt man so raus:

# mysqldump -Ad
# mysqldump --opt -AEcd

den Typ und die DB-Engine aller Tabellen in dem DBMS ausgeben:

# echo "SELECT table_schema, table_name, table_type, engine FROM information_schema.tables;" | mysql -t
+--------------------------+---------------------------------------+-------------+--------+
| table_schema             | table_name                            | table_type  | engine |
+--------------------------+---------------------------------------+-------------+--------+
...
| information_schema       | VIEWS                                 | SYSTEM VIEW | MyISAM |
| kontakt                  | adresse                               | BASE TABLE  | InnoDB |
...

MySQL commands:

Note that all text commands must be first on line and end with ';'
help    (\h)   Display this help.
?       (\?)   Synonym for `help'.
clear   (\c)   Clear command.
connect (\r)   Reconnect to the server. Optional arguments are db and host.
edit    (\e)   Edit command with $EDITOR.
ego     (\G)   Send command to mysql server, display result vertically.
exit    (\q)   Exit mysql. Same as quit.
go      (\g)   Send command to mysql server.
nopager (\n)   Disable pager, print to stdout.
notee   (\t)   Don't write into outfile.
pager   (\P)   Set PAGER [to_pager]. Print the query results via PAGER.
print   (\p)   Print current command.
quit    (\q)   Quit mysql.
rehash  (\#)   Rebuild completion hash.
source  (\.)   Execute a SQL script file. Takes a file name as an argument.
status  (\s)   Get status information from the server.
tee     (\T)   Set outfile [to_outfile]. Append everything into given outfile.
use     (\u)   Use another database. Takes database name as argument.

ERROR 1872 (HY000): Slave failed to initialize relay log info structure from the repository

will man eine Replikation aufbauen, dann kommt es gelegentlich zu dieser Fehlermeldung:

*************************** 2. row ***************************
               Slave_IO_State: 
                  Master_Host: 192.168.5.103
                  Master_User: otto
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000016
          Read_Master_Log_Pos: 918974056
               Relay_Log_File: mysql-relay-bin-live.000001
                Relay_Log_Pos: 4
        Relay_Master_Log_File: mysql-bin.000016
             Slave_IO_Running: No
            Slave_SQL_Running: No
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 1872
                   Last_Error: Slave failed to initialize relay log info structure from the repository
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 918974056
              Relay_Log_Space: 0
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 1872
               Last_SQL_Error: Slave failed to initialize relay log info structure from the repository
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 0
                  Master_UUID: 
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: 
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 160815 13:07:03
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 
            Executed_Gtid_Set: 7311df03-83de-11e5-a96b-00facb90c1a2:25839145-25853443,
dcd4eaf5-2411-11e6-b91b-842b2b6265d0:1-2,
e9c12dc7-3d36-11e6-ae3f-842b2b626ca2:1-3200
                Auto_Position: 0
         Replicate_Rewrite_DB: 
                 Channel_Name: live
           Master_TLS_Version: 

Dann kann es oft schon helfen, wenn man einfach nur das macht:

> echo "STOP SLAVE ; START SLAVE ;" | mysql -S /var/run/mysqld/mysqld_3355.sock

…sollte es dann weiterhin zu dieser Fehlermeldung kommen, zusätzlich einen Restart des DBMS:

> /etc/init.d/mysql_3355 restart
> echo "STOP SLAVE ; START SLAVE ;" | mysql -S /var/run/mysqld/mysqld_3355.sock

…sollte jetzt immer noch dieser Fehlermeldung ausgegeben werden, dann müssen wir einen RESET SLAVE machen!

Dabei ist aber Vorsicht geboten! Besonders, wenn man mit Channel_Name arbeitet!

In diesem Beispiel hat der Channel live das Problem, die andere(n) Replikation(en) laufen einwandfrei. Also dürfen wir auch nur den betroffenen Channel reseten:

> echo "RESET SLAVE FOR CHANNEL 'live';" | mysql -t -S /var/run/mysqld/mysqld_3355.sock

dann sieht die Statusausgabe so aus:

*************************** 2. row ***************************
               Slave_IO_State: 
                  Master_Host: 192.168.5.103
                  Master_User: otto
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: 
          Read_Master_Log_Pos: 4
               Relay_Log_File: mysql-relay-bin-live.000001
                Relay_Log_Pos: 4
        Relay_Master_Log_File: 
             Slave_IO_Running: No
            Slave_SQL_Running: No
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 0
              Relay_Log_Space: 0
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 0
                  Master_UUID: 
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: 
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 
            Executed_Gtid_Set: 7311df03-83de-11e5-a96b-00facb90c1a2:25839145-25853443,
dcd4eaf5-2411-11e6-b91b-842b2b6265d0:1-2,
e9c12dc7-3d36-11e6-ae3f-842b2b626ca2:1-3200
                Auto_Position: 0
         Replicate_Rewrite_DB: 
                 Channel_Name: live
           Master_TLS_Version: 

Jetzt müssen die Replikations-Daten erneut eingegeben werden:

> echo "CHANGE MASTER TO MASTER_HOST='192.168.5.103', MASTER_PORT=3306, MASTER_USER='otto', MASTER_PASSWORD='geheim', MASTER_LOG_FILE='mysql-bin.000016', MASTER_LOG_POS=918974056 FOR CHANNEL 'live';" | mysql -S /var/run/mysqld/mysqld_3355.sock
> echo "START SLAVE;" | mysql -S /var/run/mysqld/mysqld_3355.sock

Nun sollte alles prima laufen:

*************************** 2. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.5.103
                  Master_User: otto
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000016
          Read_Master_Log_Pos: 918974056
               Relay_Log_File: mysql-relay-bin-live.000002
                Relay_Log_Pos: 317
        Relay_Master_Log_File: mysql-bin.000016
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 918974056
              Relay_Log_Space: 529
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 301
                  Master_UUID: ea9680e3-0618-11e5-b548-0075169c5ba7
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 
            Executed_Gtid_Set: 7311df03-83de-11e5-a96b-00facb90c1a2:25839145-25853443,
dcd4eaf5-2411-11e6-b91b-842b2b6265d0:1-2,
e9c12dc7-3d36-11e6-ae3f-842b2b626ca2:1-3200
                Auto_Position: 0
         Replicate_Rewrite_DB: 
                 Channel_Name: live
           Master_TLS_Version: 

DB fest auf UTF-8 einstellen

> vi my.cnf
[client]
default-character-set=utf8

[mysql]
default-character-set=utf8

[mysqld]
character-set-server = utf8
collation-server = utf8_unicode_ci
init-connect='SET NAMES utf8'

Error ‚You cannot ‚ALTER‘ a log table if logging is enabled‘ on query.

STOP SLAVE;
SET GLOBAL slow_query_log = ‚OFF‘;
START SLAVE;
SHOW SLAVE STATUS\G;
SET GLOBAL slow_query_log = ‚ON‘;

DB-Benutzer löschen

# echo "DROP USER fritz" | mysql -uroot -p mysql

DB-Benutzer anlegen

/home/bin/add_db_user.sh

#!/bin/bash

# Mit diesem Script wird ein unpreveligierter User angelegt,
# der nur die Rechte SELECT, INSERT und UPDATE für genau eine
# DB bekommt.

while [ "${#}" -ne "0" ]; do
        case "$1" in
                -dbh)
                        DBHOST="${2}"
                        shift
                        ;;
                -dbn)
                        DBNAME="${2}"
                        shift
                        ;;
                -dbu)
                        DBUSER="${2}"
                        shift
                        ;;
                -dbp)
                        DBPASS="${2}"
                        shift
                        ;;
                -rp)
                        RTPASS="${2}"
                        shift
                        ;;
                -h)
                        echo "Usage: $0 -h" >&2
                        echo "Usage: $0 -dbh [DB-Host] -dbn [DB-Name] -dbu [Benutzer] -dbp [Passwort] -rp [root-Passwort]" >&2
                        echo "Usage: $0 -dbh meine.datenbank.de -dbn db_name -dbu fritz -dbp geheim -rp ganzgeheim" >&2
                        exit 1
                        ;;
                *)
                        if [ "$(echo "${1}"|egrep '^-')" ] ; then
                                echo "Der Parameter '${1}' wird nicht unterstützt!"
                        fi
                        shift
                        ;;
        esac
done

if [ -z "${DBHOST}" -o -z "${DBNAME}" -o -z "${DBUSER}" -o -z "${DBPASS}" -o -z "${RTPASS}" ] ; then
echo "
DBHOST='${DBHOST}'
DBNAME='${DBNAME}'
DBUSER='${DBUSER}'
DBPASS='${DBPASS}'
RTPASS='${RTPASS}'
"
        ${0} -h
        exit 2
fi

ping -c3 ${DBHOST}
if [ "$?" != "0" ] ; then
        echo "
        ${DBHOST} ist nicht erreichbar...
        "
        exit 3
fi


# Benutzer anlegen
echo "CREATE USER ${DBUSER} IDENTIFIED BY '${DBPASS}';" | mysql -t -h ${DBHOST} -uroot -p${RTPASS} mysql

# Blle Rechte weg
echo "REVOKE ALL PRIVILEGES,GRANT OPTION FROM ${DBUSER};" | mysql -t -h ${DBHOST} -uroot -p${RTPASS}

# bekommt nur die Rechte: SELECT, INSERT und UPDATE
echo "GRANT SELECT ON * TO ${DBUSER}; FLUSH PRIVILEGES;" | mysql -t -h ${DBHOST} -uroot -p${RTPASS} ${DBNAME}
echo "GRANT INSERT ON * TO ${DBUSER}; FLUSH PRIVILEGES;" | mysql -t -h ${DBHOST} -uroot -p${RTPASS} ${DBNAME}
echo "GRANT UPDATE ON * TO ${DBUSER}; FLUSH PRIVILEGES;" | mysql -t -h ${DBHOST} -uroot -p${RTPASS} ${DBNAME}

# Test
mysqlshow -t -h${DBHOST} -u${DBUSER} -p${DBPASS}
mysqlshow -t -h${DBHOST} -u${DBUSER} -p${DBPASS} ${DBNAME}

Backup / Dump

BINLOG/BIN-LOG von einer MySQL-DB löschen

bis zu einem bestimmten BINLOG alles löschen was älter ist:

> echo "PURGE MASTER LOGS TO 'mysql-bin.013631';" | mysql

nur die letzten 10 BINLOG liegen lassen, alle älteren löschen:

> echo "PURGE MASTER LOGS TO '$(cd /var/lib/mysql/data/ && ls -t mysql-bin.* | egrep '[0-9]' | head -n10 | tail -n1)';" | mysql

BINLOG bis zu einem bestimmten Zeitpunkt löschen:

> echo "PURGE MASTER LOGS BEFORE '2018-03-09 09:58:20';" | mysql

nur die BINLOG-Daten aus den letzten 24 Stunen liegen lassen, alle älteren löschen:

> echo "PURGE MASTER LOGS BEFORE '$(date -d"1 day ago" +"%F %T")';" | mysql

nur die BINLOG-Daten aus den letzten 3 Stunen liegen lassen, alle älteren löschen:

> echo "PURGE MASTER LOGS BEFORE '$(date -d"3 hour ago" +"%F %T")';" | mysql

nur die BINLOG-Daten aus den letzten 30 Minuten liegen lassen, alle älteren löschen:

> echo "PURGE MASTER LOGS BEFORE '$(date -d"30 minute ago" +"%F %T")';" | mysql
/root/bin/PURGE_BIN-LOGS.sh
#!/bin/bash
 
# wenn mal die Platte vollgelaufen ist,
# dann hilft nur noch dieses Skript
 
VERSION="v2019120400"
 
### die aelteste BIN-LOG-Datei loeschen
### aber die juengste nie
### egal wieviele oder wenige dort sind
rm $(ls /var/lib/mysql/data/mysql-bin.0* | head -n1)
 
### per SQL alle BIN-LOGs loeschen, die nicht von heute sind
echo "PURGE MASTER LOGS BEFORE '$(date +'%F')';" | mysql
 
echo "SHOW VARIABLES LIKE 'expire_logs_days';" | mysql -t

Speicherbelegung von MySQL-DB

> watch -n1 'df -h;echo;free;echo;pmap -d $(ps ax | fgrep -v grep | fgrep "/usr/sbin/mysqld" | sed "s/^ *//;s/ .*//") | fgrep "writeable/private:"'
mapped: 13289100K    writeable/private: 11467036K    shared: 0K

https://dev.mysql.com/doc/refman/5.7/en/memory-use.html

MAX_MEMORY_GB.sh
#!/bin/bash
 
#+ @@innodb_additional_mem_pool_size
 
echo "SELECT @@max_connections AS max_connections;" | mysql -t
for v in key_buffer_size query_cache_size innodb_buffer_pool_size innodb_log_buffer_size read_buffer_size read_rnd_buffer_size sort_buffer_size join_buffer_size binlog_cache_size thread_stack tmp_table_size
do
        #echo "echo \"SELECT ( @@${v} ) / (1024 * 1024 * 1024) AS MAX_MEMORY_GB;\" | mysql -t"
        echo "SELECT @@${v} / 1024 AS '${v} in kB';" | mysql -t
done
 
echo '################################################################################'
 
echo 'SELECT ( @@key_buffer_size
+ @@query_cache_size
+ @@innodb_buffer_pool_size
+ @@innodb_log_buffer_size
+ @@max_connections * ( @@read_buffer_size
+ @@read_rnd_buffer_size
+ @@sort_buffer_size
+ @@join_buffer_size
+ @@binlog_cache_size
+ @@thread_stack
+ @@tmp_table_size )
) / (1024 * 1024 * 1024) AS MAX_MEMORY_GB;' | mysql -t
> bash MAX_MEMORY_GB.sh
+-----------------+
| max_connections |
+-----------------+
|             600 |
+-----------------+
+-----------------------+
| key_buffer_size in kB |
+-----------------------+
|             8192.0000 |
+-----------------------+
+------------------------+
| query_cache_size in kB |
+------------------------+
|                 0.0000 |
+------------------------+
+-------------------------------+
| innodb_buffer_pool_size in kB |
+-------------------------------+
|                  8388608.0000 |
+-------------------------------+
+------------------------------+
| innodb_log_buffer_size in kB |
+------------------------------+
|                   32768.0000 |
+------------------------------+
+------------------------+
| read_buffer_size in kB |
+------------------------+
|               128.0000 |
+------------------------+
+----------------------------+
| read_rnd_buffer_size in kB |
+----------------------------+
|                   256.0000 |
+----------------------------+
+------------------------+
| sort_buffer_size in kB |
+------------------------+
|               256.0000 |
+------------------------+
+------------------------+
| join_buffer_size in kB |
+------------------------+
|               256.0000 |
+------------------------+
+-------------------------+
| binlog_cache_size in kB |
+-------------------------+
|                 32.0000 |
+-------------------------+
+--------------------+
| thread_stack in kB |
+--------------------+
|           192.0000 |
+--------------------+
+----------------------+
| tmp_table_size in kB |
+----------------------+
|               2.0000 |
+----------------------+
################################################################################
+---------------+
| MAX_MEMORY_GB |
+---------------+
|        8.6811 |
+---------------+
/root/bin/MAX_MEMORY.sh
#!/bin/sh
 
mysql -e "show variables; show status" | awk '
{
VAR[$1]=$2
}
END {
MAX_CONN = VAR["max_connections"]
MAX_USED_CONN = VAR["Max_used_connections"]
BASE_MEM=VAR["key_buffer_size"] + VAR["query_cache_size"] + VAR["innodb_buffer_pool_size"] + VAR["innodb_additional_mem_pool_size"] + VAR["innodb_log_buffer_size"]
MEM_PER_CONN=VAR["read_buffer_size"] + VAR["read_rnd_buffer_size"] + VAR["sort_buffer_size"] + VAR["join_buffer_size"] + VAR["binlog_cache_size"] + VAR["thread_stack"] + VAR["tmp_table_size"]
MEM_TOTAL_MIN=BASE_MEM + MEM_PER_CONN*MAX_USED_CONN
MEM_TOTAL_MAX=BASE_MEM + MEM_PER_CONN*MAX_CONN
 
printf "+------------------------------------------+--------------------+\n"
printf "| %40s | %15.3f MB |\n", "key_buffer_size", VAR["key_buffer_size"]/1048576
printf "| %40s | %15.3f MB |\n", "query_cache_size", VAR["query_cache_size"]/1048576
printf "| %40s | %15.3f MB |\n", "innodb_buffer_pool_size", VAR["innodb_buffer_pool_size"]/1048576
printf "| %40s | %15.3f MB |\n", "innodb_additional_mem_pool_size", VAR["innodb_additional_mem_pool_size"]/1048576
printf "| %40s | %15.3f MB |\n", "innodb_log_buffer_size", VAR["innodb_log_buffer_size"]/1048576
printf "+------------------------------------------+--------------------+\n"
printf "| %40s | %15.3f MB |\n", "BASE MEMORY", BASE_MEM/1048576
printf "+------------------------------------------+--------------------+\n"
printf "| %40s | %15.3f MB |\n", "sort_buffer_size", VAR["sort_buffer_size"]/1048576
printf "| %40s | %15.3f MB |\n", "read_buffer_size", VAR["read_buffer_size"]/1048576
printf "| %40s | %15.3f MB |\n", "read_rnd_buffer_size", VAR["read_rnd_buffer_size"]/1048576
printf "| %40s | %15.3f MB |\n", "join_buffer_size", VAR["join_buffer_size"]/1048576
printf "| %40s | %15.3f MB |\n", "thread_stack", VAR["thread_stack"]/1048576
printf "| %40s | %15.3f MB |\n", "binlog_cache_size", VAR["binlog_cache_size"]/1048576
printf "| %40s | %15.3f MB |\n", "tmp_table_size", VAR["tmp_table_size"]/1048576
printf "+------------------------------------------+--------------------+\n"
printf "| %40s | %15.3f MB |\n", "MEMORY PER CONNECTION", MEM_PER_CONN/1048576
printf "+------------------------------------------+--------------------+\n"
printf "| %40s | %18d |\n", "Max_used_connections", MAX_USED_CONN
printf "| %40s | %18d |\n", "max_connections", MAX_CONN
printf "+------------------------------------------+--------------------+\n"
printf "| %40s | %15.3f MB |\n", "TOTAL (MIN)", MEM_TOTAL_MIN/1048576
printf "| %40s | %15.3f MB |\n", "TOTAL (MAX)", MEM_TOTAL_MAX/1048576
printf "+------------------------------------------+--------------------+\n"
}'
> /root/bin/MAX_MEMORY.sh
+------------------------------------------+--------------------+
|                          key_buffer_size |           8.000 MB |
|                         query_cache_size |           0.000 MB |
|                  innodb_buffer_pool_size |        8192.000 MB |
|          innodb_additional_mem_pool_size |           0.000 MB |
|                   innodb_log_buffer_size |          32.000 MB |
+------------------------------------------+--------------------+
|                              BASE MEMORY |        8232.000 MB |
+------------------------------------------+--------------------+
|                         sort_buffer_size |           0.250 MB |
|                         read_buffer_size |           0.125 MB |
|                     read_rnd_buffer_size |           0.250 MB |
|                         join_buffer_size |           0.250 MB |
|                             thread_stack |           0.188 MB |
|                        binlog_cache_size |           0.031 MB |
|                           tmp_table_size |           0.002 MB |
+------------------------------------------+--------------------+
|                    MEMORY PER CONNECTION |           1.096 MB |
+------------------------------------------+--------------------+
|                     Max_used_connections |                118 |
|                          max_connections |                600 |
+------------------------------------------+--------------------+
|                              TOTAL (MIN) |        8361.293 MB |
|                              TOTAL (MAX) |        8889.422 MB |
+------------------------------------------+--------------------+

im RAM

> echo "SELECT @@innodb_buffer_pool_size/1024/1024 AS 'innodb_buffer_pool_size in MB';" | mysql -t -S /var/run/mysqld/mysqld_3319.sock
+-------------------------------+
| innodb_buffer_pool_size in MB |
+-------------------------------+
|                 2048.00000000 |
+-------------------------------+

Weil InnoDB auch noch andere Puffer benutzt, muss der hier angegebene Wert mind. verdoppelt werden, um den (unter Last) tatsächlich verwendeten RAM abzuschätzen.

der aktuell tatsächlich verwendete RAM, kann so ermittelt werden:

> pmap -d $(ps ax | fgrep -v grep | fgrep "/usr/sbin/mysqld" | sed "s/^ *//;s/ .*//") | fgrep "writeable/private:"
/root/bin/MySQL-Speicherplatzverbrauch_im_RAM.sh
#!/bin/bash
 
#
# Dieses Skript zeigt, wieviel Arbeitsspeicher
# von welchem (laufenden) DBMS verwendet wird.
#
 
### damit "sort -n" das Dezimaltrennzeichen richtig deutet
LANG=C
 
### PIDs der MySQL-Instanzen finden
PIDS="$(pidof mysqld)"
 
### Schleife über jede PID einzeln
for EINE_PID in ${PIDS}
do
        ### zur PID zugehörige MySQL-Konfigurationsdatei finden
        for CNF in $(ps ax | fgrep -v 'grep ' | fgrep -v 'awk ' | egrep "^[ \t]*${EINE_PID} " | tr -s ' ' '\n' | egrep '[-][-]defaults-file=')
        do
                ### aus der Konfiguration die IP+Port holen
                ADRESSE_PORT="$(my_print_defaults ${CNF} mysqld | egrep '[-][-]port=|[-][-]bind-address=' | sort | awk -F'=' '{print $2}' | tr -s '\n' ' ' | awk '{print $1":"$2}')"
                #echo "${ADRESSE_PORT}"
 
                ### Speicherbelegung der PID errechnen
                SPEICHER="$(pmap ${EINE_PID} | fgrep ' [ ' | awk '{print $2}' | sed 's/K/*1024/;s/M/*1024*1024/;s/G/*1024*1024*1024/' | bc -l | awk '{z=$1;s+=z}END{print s/1024/1024/1024,"GB"}')"
                echo "${SPEICHER} - ${ADRESSE_PORT}"
        done
done | sort -n

auf Platte

/root/bin/mysql-speicherverbrauch.sh
#!/bin/bash
 
#
# tatsaechlicher Speicherplatzbedarf von diesem DBMS
#
 
VERSION="v2017033100"
#MYSQL_PROG="mysql --defaults-file=/etc/mysql/debian.cnf -t"
MYSQL_PROG="mysql --defaults-file=/root/.my.cnf -t"
 
 
### Übersicht
echo "
SELECT
        table_schema,
        table_name,
        data_length,
        index_length,
        data_length,
        index_length,
        data_free
FROM
        information_schema.tables
WHERE
        data_length IS NOT NULL
        AND data_length<>'information_schema'
        AND data_length<>'performance_schema'
        AND data_length<>'sys'
ORDER BY data_length DESC
;" | ${MYSQL_PROG}
 
 
### Summen
echo "  
SELECT 
        table_schema AS 'Datenbankname',
        table_name,
        ROUND( SUM( data_length ) / 1024 / 1024, 3 ) AS 'Daten (MB)',
        ROUND( SUM( index_length ) / 1024 / 1024, 3 ) AS 'Index (MB)',
        ROUND( SUM( data_length + index_length ) / 1024 / 1024, 3 ) AS 'Gesamt (MB)',
        ROUND( SUM( data_free ) / 1024 / 1024, 3 ) AS 'Freier Speicher (MB)'
FROM
        information_schema.tables
GROUP BY table_schema
ORDER BY 5 DESC
;" | ${MYSQL_PROG}

Mit OPTIMIZE TABLE kann der Speicherbereich, der von der Datei noch belegt wird aber nicht mehr benötigt wird, wieder frei gegeben.

Tabellen defragmentieren - leeren InnoDB-Speicherplatz wieder frei gebenOPTIMIZE TABLE

MySQL-Tabellen reparieren

REPAIR TABLE `datenbankname`.`tabellenname` USE_FRM;

alle MySQL-DB-Back-Ends reparieren

# mysqlcheck --repair -uBENUTZER -pPASSWORT meine_datenbank meine_tabelle
# mysqlcheck --analyze -uBENUTZER -pPASSWORT meine_datenbank meine_tabelle
# mysqlcheck --optimize -uBENUTZER -pPASSWORT meine_datenbank meine_tabelle

nur MyISAM reparieren

Fehlerüberprüfung

Überprüfung:

# myisamchk -c /var/lib/mysql/meine_datenbank/meine_tabelle.MYI

Reparatur möglichkeiten

Wenn bei der obigen Überprüfung Fehler aufgetreten sind, dann wie folgt weiter.

alte Reparaturreste entfernen:

# rm -f /var/lib/mysql/meine_datenbank/meine_tabelle.TMD
schnelle Reparatur
# myisamchk -r /var/lib/mysql/meine_datenbank/meine_tabelle.MYI
genaue Reparatur

Wenn bei der Schnellreparatur mir "-r" diese Fehlermeldung kommt:

# myisamchk -r /var/lib/mysql/meine_datenbank/meine_tabelle.MYI
myisamchk: error: myisam_sort_buffer_size is too small

dann hilft nur noch die Option "-o":

# myisamchk -o /var/lib/mysql/meine_datenbank/meine_tabelle.MYI

SQL

Den Inhalt einer Tabelle in eine andere Tabelle kopieren

Hier wird eine neue Tabelle (test_datenbank.test_tabelle2) als exakte Kopie einer alten Tabelle (test_datenbank.test_tabelle1) angelegt:

echo "CREATE TABLE test_datenbank.test_tabelle2 LIKE test_datenbank.test_tabelle1;" | mysql

Hier werden die Daten aus der alten Tabelle (test_datenbank.test_tabelle1) in die neue Tabelle (test_datenbank.test_tabelle2) kopiert:

echo "INSERT INTO test_datenbank.test_tabelle2 SELECT * FROM test_datenbank.test_tabelle1;" | mysql

Nur bestimmte Spalten einer Tabelle in eine andere Tabelle kopieren

Es sollen die inhalte bestimmter Spalten (datum,betrag,gegenstand,name,beschreibung) einer Tabelle (test_tabelle1) in eine andere Tabelle (test_tabelle2) kopiert werden:

echo "INSERT INTO test_datenbank.test_tabelle2 (datum,betrag,gegenstand,name,beschreibung) SELECT datum,betrag,gegenstand,name,beschreibung FROM test_datenbank.test_tabelle1;" | mysql

MySQL mit partitionierten Tabellen

SQL-Aufrufe (Query)

Datenbank anlegen:

> echo "CREATE DATABASE IF NOT EXISTS testdb;" | mysql
> mysqlshow testdb

Tabelle in der Datenbank anlegen:

> echo "CREATE TABLE benutzer (id INT, name VARCHAR(64));" | mysql testdb
> mysqlshow testdb benutzer
> echo "SELECT * FROM benutzer WHERE name LIKE 'm%' ORDER BY id ASC;" | mysql -t testdb

einen Datensatz in die Tabelle einspielen:

> echo "INSERT INTO benutzer (id, name) VALUES ('1','Fritz');" | mysql testdb
> echo "INSERT INTO benutzer (id, name) VALUES ('2','Mustermann');" | mysql testdb
> echo "SELECT * FROM benutzer ORDER BY id ASC;" | mysql -t testdb
> echo "SELECT * FROM benutzer WHERE name LIKE 'm%' ORDER BY id ASC;" | mysql -t testdb

einen Datensatz in der Tabelle ändern:

> echo "UPDATE benutzer SET name='Musterfrau' WHERE name='Mustermann';" | mysql testdb
> echo "SELECT * FROM benutzer ORDER BY id ASC;" | mysql -t testdb

einen Datensatz aus der Tabelle löschen:

> echo "DELETE FROM benutzer WHERE id=1;" | mysql testdb
> echo "SELECT * FROM benutzer ORDER BY id ASC;" | mysql -t testdb

die vorhandene Tabelle um drei Spalten erweitern:

> echo "ALTER TABLE benutzer ADD vorname VARCHAR(64) AFTER name" | mysql testdb
> echo "ALTER TABLE benutzer ADD eingetragen TIMESTAMP DEFAULT CURRENT_TIMESTAMP AFTER vorname" | mysql testdb
> echo "ALTER TABLE benutzer ADD aktualisiert TIMESTAMP DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP AFTER eingetragen;" | mysql testdb
> echo "SELECT * FROM benutzer ORDER BY id ASC;" | mysql -t testdb

die ganze Datenbank, mit allen Tabellen darin, löschen:

> echo "DROP DATABASE IF EXISTS testdb;" | mysql

siehe auch: MySQL Subquery / MySQL SubSELECT

Benutzer anlegen und löschen

> echo "INSERT INTO user (host,user) VALUES ('%','fritz');" | mysql -uroot -p[passwort] mysql
> echo "DROP USER fritz;" | mysql -uroot -p[passwort] mysql

Passwort ändern

seit die Passwortspalte nicht mehr "password" heißt, sondern "authentication_string", muss das Kommando so aussehen:

> echo "UPDATE user SET authentication_string=password('geheimes Passwort') where user='Benutzername';" | mysql mysql
> mysqladmin reload

Root-Passwort ändern (vor MySQL 8.0):

> echo "UPDATE mysql.user SET authentication_string=PASSWORD('geheim') WHERE User='root';" | mysql

> echo "CREATE USER rouser IDENTIFIED WITH mysql_native_password BY 'geheim';" | mysql
> echo "UPDATE mysql.user SET host='%',authentication_string=PASSWORD('geheim'),plugin='mysql_native_password' WHERE user='root';" | mysql

root-Passwort ist bekannt

Passwort ändern:

# echo "UPDATE user SET password=password('neugeheim') where user='root';" | mysql -uroot [-paltgeheim]
# mysqladmin reload

Jetzt sollte ein:

# mysql -uroot -pgeheim

funktionieren.

ODER

# mysql -uroot -e "UPDATE user SET password=password('geheim') WHERE user='root';" mysql
# mysqladmin reload

ODER

# mysqladmin -uroot -p'altes_Passwort' password 'neues_Passwort'
# mysqladmin reload

root-Passwort ist unbekannt

http://www.howtoforge.com/reset-forgotten-mysql-root-password

> service mysql stop
> screen -d -m -S mysql mysqld_safe --skip-grant-tables
> echo "UPDATE user SET Password=PASSWORD('geheim') where user='root'; FLUSH PRIVILEGES;" | mysql mysql
> ps wwaux|fgrep -v grep|fgrep -v awk|awk '/mysql/{print $2}'
10259
> kill -9 10259

dem Benutzer-Rechte erteilen und entziehen

alle Rechte entziehen:

# echo "REVOKE ALL PRIVILEGES, GRANT OPTION FROM fritz;" | mysql -u root -p

alle Rechte erteilen:

# echo "GRANT ALL PRIVILEGES ON *.* TO 'fritz'@'%' IDENTIFIED BY 'geheim';FLUSH PRIVILEGES;" | mysql -u root -p

ALTER-Rechte erteilen:

# echo "GRANT ALTER ON *.* TO fritz;FLUSH PRIVILEGES;" | mysql -u root -p

ALTER-Rechte entziehen:

# echo "REVOKE ALTER ON *.* FROM fritz;FLUSH PRIVILEGES;" | mysql -u root -p
Grant-Beispiel

Als erstes legen wir uns die MySQL-Passwort-Datei an, damit wir nicht bei jedem Kommando das Passwort mit eingeben müssen:

> vi ~/.my.cnf
[client]
host     = localhost
user     = root
password = "geheim"
socket   = /var/run/mysqld/mysqld.sock

http://dev.mysql.com/doc/refman/5.1/de/grant.html

> ssh root@DatenbankHostname
> echo "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%';GRANT GRANT OPTION ON *.* TO 'root'@'%';FLUSH PRIVILEGES;" | mysql
> exit
> echo "DROP USER fritz;" | mysql -t -h DatenbankHostname mysql
> echo "CREATE USER fritz IDENTIFIED BY 'geheim';" | mysql -t -h DatenbankHostname mysql
> echo "REVOKE ALL PRIVILEGES,GRANT OPTION FROM 'fritz'@'%';" | mysql -t -h DatenbankHostname mysql
> echo "GRANT SHOW DATABASES ON * TO 'fritz'@'%';FLUSH PRIVILEGES;" | mysql -t -h DatenbankHostname
> echo "GRANT SELECT ON * TO 'fritz'@'%';FLUSH PRIVILEGES;" | mysql -t -h DatenbankHostname Datenbankname
> echo "GRANT INSERT ON * TO 'fritz'@'%';FLUSH PRIVILEGES;" | mysql -t -h DatenbankHostname Datenbankname
> echo "GRANT UPDATE ON * TO 'fritz'@'%';FLUSH PRIVILEGES;" | mysql -t -h DatenbankHostname Datenbankname
> echo "GRANT DELETE ON * TO 'fritz'@'%';FLUSH PRIVILEGES;" | mysql -t -h DatenbankHostname Datenbankname
> echo "GRANT CREATE ON * TO 'fritz'@'%';FLUSH PRIVILEGES;" | mysql -t -h DatenbankHostname Datenbankname
> echo "GRANT DROP ON * TO 'fritz'@'%';FLUSH PRIVILEGES;" | mysql -t -h DatenbankHostname Datenbankname
> echo "GRANT INDEX ON * TO 'fritz'@'%';FLUSH PRIVILEGES;" | mysql -t -h DatenbankHostname Datenbankname
> echo "GRANT ALTER ON * TO 'fritz'@'%';FLUSH PRIVILEGES;" | mysql -t -h DatenbankHostname Datenbankname
> echo "GRANT CREATE TEMPORARY TABLES ON * TO 'fritz'@'%';FLUSH PRIVILEGES;" | mysql -t -h DatenbankHostname Datenbankname
> echo "GRANT CREATE VIEW ON * TO 'fritz'@'%';FLUSH PRIVILEGES;" | mysql -t -h DatenbankHostname Datenbankname
> echo "GRANT SHOW VIEW ON * TO 'fritz'@'%';FLUSH PRIVILEGES;" | mysql -t -h DatenbankHostname Datenbankname
> echo "GRANT TRIGGER ON * TO 'fritz'@'%';FLUSH PRIVILEGES;" | mysql -t -h DatenbankHostname Datenbankname

dem Benutzer nur bestimmte Rechte geben

als erstes nehmen wir dem neuen User ALLE Rechte:

# echo "REVOKE ALL PRIVILEGES, GRANT OPTION FROM fritz;" | mysql -hdbrechner -uroot -pgeheim datenbank

jetzt bekommt er nur Leserechte auf seine Datenbanken:

# echo "GRANT SELECT ON * TO fritz;FLUSH PRIVILEGES;" | mysql -hdbrechner -uroot -pgeheim datenbank

zum Schluss bekommt er noch etwas Schreibrechte auf einzelne Tabellen:

# echo "GRANT INSERT ON tabelle01 TO fritz;FLUSH PRIVILEGES;" | mysql -hdbrechner -uroot -pgeheim datenbank

Es kann immer nur eine einzige Tabelle angegeben werden!

jetzt lassen wir uns seine aktuellen Rechte noch einmal anzeigen, damit wir sicher sind, dass alles nach unserem Wunsch ausgeführt wurde:

# echo "SHOW GRANTS FOR 'fritz' \G;" | mysql -hdbrechner -uroot -pgeheim

oder

# echo "SHOW GRANTS FOR 'fritz';" | mysql -hdbrechner -uroot -pgeheim
DB-User mit eingeschränkten Rechten anlegen
# echo "GRANT SELECT,UPDATE,INSERT,DELETE ON Tabelle TO 'Benutzer'@'ClientRechner' IDENTIFIED BY 'geheim'; FLUSH PRIVILEGES;" | mysql --defaults-file=meine_zugangsdaten.cnf -t -hServerRechner Datenbank

Hier ist ein Beispiel, in dem der User fritz mit dem Passwort geheim und den Rechten SELECT,UPDATE,INSERT,DELETE für die DB datenbank auf dem DBMS-Host dbrechner angelegt wird:

# echo "DROP USER fritz;CREATE USER fritz IDENTIFIED BY 'geheim';REVOKE ALL PRIVILEGES, GRANT OPTION FROM fritz; GRANT SELECT,UPDATE,INSERT,DELETE ON * TO 'fritz'@'%' IDENTIFIED BY 'geheim';FLUSH PRIVILEGES;" | mysql -uroot -p -hdbrechner datenbank

DB-Backup

MySQLDump benötigt mindestens diese Berechtigungen:

> echo "GRANT SELECT, RELOAD, SUPER, LOCK TABLES, REPLICATION CLIENT, EVENT, TRIGGER ON *.* TO 'backup'@'localhost' IDENTIFIED BY 'geheim'; FLUSH PRIVILEGES;" | mysql
> echo "GRANT CREATE, INSERT, DROP ON mysql.ibbackup_binlog_marker TO 'backup'@'localhost';" | mysql
> echo "GRANT CREATE, INSERT, DROP ON mysql.backup_progress TO 'backup'@'localhost';" | mysql
> echo "GRANT CREATE, INSERT, SELECT, DROP ON mysql.backup_history TO 'backup'@'localhost';" | mysql
> echo "GRANT CREATE TEMPORARY TABLES ON mysql.* TO 'backup'@'localhost';" | mysql
> echo "FLUSH PRIVILEGES;" | mysql

Datenbank anlegen und löschen

> echo "CREATE DATABASE IF NOT EXISTS meinedb;" | mysql -hdbrechner -uroot -pgeheim datenbank
> echo "DROP DATABASE IF EXISTS meinedb;" | mysql -hdbrechner -uroot -pgeheim datenbank

Tabelle anlegen und löschen

eine neue Tabelle anlegen:

# echo "CREATE TABLE IF NOT EXISTS tabelle01;" | mysql -hdbrechner -uroot -pgeheim datenbank

die ganze Tabelle wird komplett gelöscht:

# echo "DROP TABLE IF EXISTS tabelle01;" | mysql -hdbrechner -uroot -pgeheim datenbank

Spalte in einer Tabelle ändern

https://stackoverflow.com/questions/22668024/how-to-change-column-size-of-varchar-type-in-mysql?rq=1

Tabelle anlegen:

> echo "CREATE TABLE test (id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, info VARCHAR(32)) ENGINE=InnoDB DEFAULT CHARSET=utf8;" | mysql datenbank
> echo "SHOW CREATE TABLE test;" | mysql -t datenbank

Spaltentyp von VARCHAR(32) in VARCHAR(64) ändern

> echo "ALTER TABLE test MODIFY COLUMN info VARCHAR(64);" | mysql datenbank
> echo "SHOW CREATE TABLE test;" | mysql -t datenbank

AUTO_INCREMENT übernehmen

so wird der AUTO_INCREMENT mit angezeigt:

echo 'SHOW CREATE TABLE `testdb`;' | mysql

so wird der AUTO_INCREMENT von vorlagedb nicht mit in die testdb übernommen:

echo 'CREATE TABLE `testdb` LIKE `vorlagedb`;' | mysql ${DB}

Datensätze anlegen, ändern und löschen

einen Datensatz anlegen bzw. in die Tabelle schreiben:

# echo "INSERT INTO tabelle01 (spalte01,spalte02) VALUES ('wert01','wert02');" | mysql -uroot -pgeheim datenbank

einen Datensatz ändern:

# echo "UPDATE tabelle01 SET spalte01 = 'neuer Wert' WHERE spalte02 = 'Bedingungswert';" | mysql -h myserver -u fritz -pgeheim datenbank

alle Datensätze mit "alte Daten" in der Spalte "spalte", werden gelöscht:

# echo "DELETE FROM tabelle01 WHERE spalte='alte Daten';" | mysql -hdbrechner -uroot -pgeheim datenbank

alle Datensätze, die die Zeichenkette "neu" in der Spalte "spalte" haben werden nicht gelöscht, der Rest wird gelöscht:

# echo "DELETE FROM tabelle01 WHERE spalte NOT LIKE '%neu%';" | mysql -hdbrechner -uroot -pgeheim datenbank

Die "DELETE"-Anweisung benötigt IMMER eine "WHERE"-Bedingung!

sonstiges

Einen passwortlosen User mit sehr eingeschränkten Rechten anlegen:

# echo "DROP USER fritz;DROP DATABASE IF EXISTS meinedb;" | mysql -uroot -p[passwort] mysql
# echo "CREATE DATABASE meinedb;" | mysql -uroot -p[passwort] mysql
# echo "INSERT INTO user (host,user) VALUES ('%','fritz');" | mysql -uroot -p[passwort] mysql
# echo "FLUSH PRIVILEGES;" | mysql -uroot -p[passwort] mysql
# echo "REVOKE ALL ON *.* TO fritz;" | mysql -uroot -p[passwort] meinedb
# echo "GRANT SELECT ON * TO fritz;" | mysql -uroot -p[passwort] meinedb
# echo "FLUSH PRIVILEGES;" | mysql -uroot -p[passwort] meinedb

"fritz" kann jetzt nur die Tabellen aus "meinedb" lesen, sonst nix.

einen Benutzer anlegen:

# CREATE USER fritz IDENTIFIED BY 'Geheim';

ihm alle Rechte nehmen:

# REVOKE ALL PRIVILEGES ON *.* FROM webteam;

ihm Leserechte für die DB "meinedb" geben:

# GRANT SELECT ON meinedb.* TO 'fritz'@'%' IDENTIFIED BY 'Geheim';

Datenbanken und Tabellen anzeigen:

zeigt alle Datenbanken:

# mysqlshow -uroot -pgeheim

zeigt alle Tabellen von [DATENBANK]:

# mysqlshow -uroot -pgeheim [DATENBANK]

ODER

in die "Master-Datenbank" gehen:

> use mysql;

zeigt alle Datenbanken:

> show databases;

zeigt alle Tabellen von mysql:

> show tables;

den Inhalt der Tabelle "[tabelle]" anzeigen:

> SELECT * FROM [tabelle];

User anlegen, DB anlegen und dem User die Zugriffsrechte auf die DB geben:

# echo "CREATE USER dbuser IDENTIFIED BY 'geheim';
CREATE DATABASE IF NOT EXISTS [Datenbankname];
GRANT ALL ON [Datenbankname].* TO dbuser@localhost;" | mysql -u root -p

MySQL starten, ohne das Passwörter abgefragt werden:

# /usr/bin/safe_mysqld --skip-grant-tables

oder

# /usr/bin/mysqld_safe --skip-grant-tables

Passwort ändern:

# echo "SET PASSWORD FOR dbuser = PASSWORD('geheim');" | mysql -u root -p

User löschen:

# echo "DROP USER [böserjunge];" | mysql -t -h localhost -u root -pgeheim

Tabellenstruktur anzeigen:

# echo "SHOW CREATE TABLE [Tabellenname]" | mysql -t -h localhost -uroot -p [Datenbankname]

Datenbank anlegen:

# echo "CREATE DATABASE [Datenbankname];" | mysql -t -h localhost -uroot -p
# echo "CREATE DATABASE IF NOT EXISTS [Datenbankname];" | mysql -t -h localhost -uroot -p

Datenbank löschen:

# echo "DROP DATABASE [Datenbankname];" | mysql -t -h localhost -uroot -p [Datenbankname]
# echo "DROP DATABASE IF EXISTS [Datenbankname];" | mysql -t -h localhost -uroot -p [Datenbankname]

Tabelle anlegen:

# echo "CREATE TABLE [Tabellenname] (timestamp DATETIME)" | mysql -t -h localhost -uroot -p [Datenbankname]

In der Praxis sieht eine Tabelle eher etwas komplexer aus:

# echo "CREATE DATABASE IF NOT EXISTS [Datenbankname];
USE [Datenbankname];

CREATE TABLE IF NOT EXISTS [Tabellenname] (
timestamp DATETIME,
resource_id SMALLINT,
hostname VARCHAR(254) default NULL,
ip4 VARCHAR(4096) default NULL,
mac VARCHAR(2048) default NULL,
bios_release_date VARCHAR(256) default NULL,
bios_manufacturer VARCHAR(256) default NULL,
bios_product_name VARCHAR(256) default NULL,
bios_serial_number VARCHAR(256) default NULL,
cpu_anzahl SMALLINT,
bus VARCHAR(8) default NULL,
vm VARCHAR(8) default NULL,
htt SMALLINT,
cpu_family VARCHAR(256) default NULL,
cpu_manufacturer VARCHAR(256) default NULL,
cpu_id VARCHAR(256) default NULL,
cpu_signature VARCHAR(256) default NULL,
cpu_core_count SMALLINT,
cpu_core_enabled SMALLINT,
memtotal VARCHAR(256) default NULL,
hdd VARCHAR(256) default NULL,
PRIMARY KEY (resource_id),
KEY (bios_serial_number),
KEY mac (mac)
) TYPE=MyISAM;" | mysql -t -h localhost -uroot -p

Tabelle löschen:

# echo "DROP TABLE [Tabellenname];" | mysql -t -h localhost -uroot -p [Datenbankname]

Alle Datensätze löschen:

# echo "DELETE FROM [Tabellenname];" | mysql -t -h localhost -uroot -p [Datenbankname]

Einen Datensatz löschen:

# echo "DELETE FROM [Tabellenname] WHERE [Spalte]='Wert';" | mysql -t -h localhost -uroot -p [Datenbankname]

Weitere Beispiele:

DB-Client-Programm: mysql
DB-Server         : myserver
DB-Namen          : [DatenBank]
TAB-Namen         : [DBTabelle]

Tabelle als Datei exportieren, hierbei gelten die MySQL-Standardwerte für das Dateiformat:

# echo "SELECT *
INTO OUTFILE '/tmp/[DBTabelle].txt'
FROM [DBTabelle] LIMIT 10;" | mysql -h myserver -u${DATABASE_USER} -p${DATABASE_PASSWORD} [DatenBank]

Tabelle als CSV-Datei exportieren:

# echo "SELECT *
INTO OUTFILE '/tmp/[DBTabelle].csv'
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM [DBTabelle] LIMIT 10;" | mysql -h myserver -u${DATABASE_USER} -p${DATABASE_PASSWORD} [DatenBank]

Tabelle als CSV-Datei (Semikolon getrennt) exportieren:

# echo "SELECT *
INTO OUTFILE '/tmp/[DBTabelle].csv'
FIELDS TERMINATED BY ';'
LINES TERMINATED BY '\n'
FROM [DBTabelle] LIMIT 10;" | mysql -h myserver -u${DATABASE_USER} -p${DATABASE_PASSWORD} [DatenBank]

Die Tabelle als CSV-Datei (Semikolon getrennt) wieder importieren (das ist sauschnell, weil hierbei keine Indizes aktuallisiert werden):

# echo "LOAD DATA LOCAL INFILE '/tmp/[DBTabelle].csv' INTO TABLE [DBTabelle] FIELDS TERMINATED BY ';';" | mysql -h myserver -u${DATABASE_USER} -p${DATABASE_PASSWORD} [DatenBank]

MySQL - LOAD DATA INFILE

#!/bin/bash

#
# Dieses Skript schreibt von der angegebenen Datenbank
# jede Tabelle in eine eigene CSV-Datei.
#

DATENBANK="${1}"

if [ -z "${DATENBANK}" ] ; then
        echo "${0} Datenbank"
        exit 1
else
        mkdir "${DATENBANK}"
        chmod 0777 "${DATENBANK}"
        cd "${DATENBANK}"
        VERZEICHNIS="$(pwd)"
fi

mysqlshow "${DATENBANK}" | egrep -v "${DATENBANK}|Tables" | awk '{print $2}' | egrep -v '^$' | while read TABELLE
do
        echo "${VERZEICHNIS}/${TABELLE}"
        #echo "echo \"SELECT * INTO OUTFILE '${VERZEICHNIS}/${TABELLE}.csv' FIELDS TERMINATED BY ';' LINES TERMINATED BY '\n' FROM ${TABELLE};\" | mysql -t ${DATENBANK}"
        echo "SELECT * INTO OUTFILE '${VERZEICHNIS}/${TABELLE}.csv' FIELDS TERMINATED BY ';' LINES TERMINATED BY '\n' FROM ${TABELLE};" | mysql -t ${DATENBANK}
done
#!/bin/bash

#
# Dieses Skript liest die CSV-Dateien aus dem aktuellen Verzeichnis in die angegebene Datenbank.
#

DATENBANK="${1}"

if [ -z "${DATENBANK}" ] ; then
        echo "${0} Datenbank"
        exit 1
fi

ls *.csv | sed 's/[.]csv$//' | while read TABELLE
do
        echo "${TABELLE}"
        echo "LOAD DATA LOCAL INFILE '${TABELLE}.csv' INTO TABLE ${TABELLE} FIELDS TERMINATED BY ';';" | mysql ${DATENBANK}
done

Datenbanken zeigen:

# echo "SHOW DATABASES" | mysql -h myserver -u fritz
# mysqlshow -h myserver -u fritz -p
# mysqlshow -t -h myserver -u fritz -p

Tabellen zeigen:

# echo "SHOW TABLES" | mysql -h myserver -u fritz [DatenBank]
# mysqlshow -h myserver -u fritz [DatenBank] -p
# mysqlshow -t -h myserver -u fritz [DatenBank] -p

Tabelleninhalt zeigen:

# echo "SELECT * FROM [DBTabelle]" | mysql -h myserver -u fritz -p [DatenBank]
# echo "SELECT * FROM [DBTabelle]" | mysql -t -h myserver -u fritz [DatenBank] -p

SUBSTRING:

# echo "SELECT hostname FROM belastungswaechter LIMIT 1;" | mysql -N -ufritz -pgeheim -hserver datenbank
rechnername.domain.de

# echo "SELECT SUBSTRING_INDEX(hostname,'.',1) FROM belastungswaechter LIMIT 1;" | mysql -N -ufritz -pgeheim -hserver datenbank
rechnername

# echo "SELECT SUBSTRING_INDEX(hostname,'.',2) FROM belastungswaechter LIMIT 1;" | mysql -N -ufritz -pgeheim -hserver datenbank
rechnername.domain

# echo "SELECT SUBSTRING_INDEX(hostname,'.',-2) FROM belastungswaechter LIMIT 1;" | mysql -N -ufritz -pgeheim -hserver datenbank
domain.de

IP-Adressen in numerischer Reihenfolge anzeigen:

# echo "SELECT * FROM [DBTabelle] ORDER BY INET_ATON(ip_address) LIMIT 10;" | mysql -h myserver -u${DATABASE_USER} -p${DATABASE_PASSWORD} [DatenBank]

Tabelleninhalt nach der 3. Spalte sortieren (nur die ersten 10 Zeilen:

# echo "SELECT spalte1,spalte2,spalte3 FROM [DBTabelle] ORDER BY 3 ASC LIMIT 10" | mysql -h myserver -u fritz -p [DatenBank]

Tabelleninhalt in umgekehrtsortierter Reihenfolge zeigen (nur die letzten 10 Zeilen):

# echo "SELECT spalte1,spalte2,spalte3 FROM [DBTabelle] ORDER BY 3 DESC LIMIT 10" | mysql -h myserver -u fritz -p [DatenBank]

eine Liste aller unterschiedlichen Einträge aus der Spalte 3 zeigen (nur die letzten 10 Zeilen):

# echo "SELECT spalte1,spalte2,spalte3 FROM [DBTabelle] GROUP BY 3 ORDER BY 3 DESC LIMIT 10" | mysql -h myserver -u fritz -p [DatenBank]

Wichtig ist hierbei, dass "GROUP BY" immer vor "ORDER BY" stehen muss!

MySQL kann auch mit RegEx umgehgen, hier mal zwei Beispiele:

die letzten 50 Einträge anzeigen, die älter als 7 Tage sind (Spalte "DeviceReportedTime") und eine IP in der Spalte "Message" enthalten:

# echo "SELECT ID,DeviceReportedTime,Facility,FromHost,Message,SysLogTag FROM SystemEvents WHERE DeviceReportedTime < '$(date -d-7days +'%F %T')' AND Message REGEXP '[0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}' ORDER BY ID DESC LIMIT 50;" | mysql -t -ursyslog -p Syslog

Alle Datensätze löschen, die älter als 180 Tage sind (Spalte "DeviceReportedTime") und eine IP in der Spalte "Message" enthalten:

# echo "DELETE FROM SystemEvents WHERE DeviceReportedTime < '$(date -d-180days +'%F %T')' AND Message REGEXP '[0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}';"

Weitere Beispiele gibt es hier: http://dev.mysql.com/doc/refman/5.1/de/regexp.html und hier http://gnosis.cx/publish/programming/regular_expressions.html

Anzeige der Anzahl der Einträge pro Spalte3:

# echo "SELECT spalte3,COUNT(*) FROM [DBTabelle] GROUP BY 1 ORDER BY 1 DESC LIMIT 10" | mysql -h myserver -u fritz -p [DatenBank]

Will man den Wert in der "Spalte1" auf "neuer Wert" setzen, wenn die Bedingung erfüllt ist, dass der Wert "Bedingungswert" in der "Spalte2" vorhanden ist, dann geht das so:

# echo "UPDATE [DBTabelle] SET [Spalte1] = 'neuer Wert' WHERE [Spalte2] = 'Bedingungswert';" | mysql -h myserver -u fritz -p [DatenBank]

Infos zu den Tabellen abrufen:

# echo "SELECT table_name, table_type, engine FROM information_schema.tables;"|mysql -t -h localhost -uroot -p openqrm
+---------------------------------------+-------------+--------+
| table_name                            | table_type  | engine |
+---------------------------------------+-------------+--------+
| CHARACTER_SETS                        | SYSTEM VIEW | MEMORY | 
| COLLATIONS                            | SYSTEM VIEW | MEMORY | 
| COLLATION_CHARACTER_SET_APPLICABILITY | SYSTEM VIEW | MEMORY | 
| COLUMNS                               | SYSTEM VIEW | MyISAM | 
| COLUMN_PRIVILEGES                     | SYSTEM VIEW | MEMORY | 
| KEY_COLUMN_USAGE                      | SYSTEM VIEW | MEMORY | 
| PROFILING                             | SYSTEM VIEW | MEMORY | 
| ROUTINES                              | SYSTEM VIEW | MyISAM | 
| SCHEMATA                              | SYSTEM VIEW | MEMORY | 
| SCHEMA_PRIVILEGES                     | SYSTEM VIEW | MEMORY | 
| STATISTICS                            | SYSTEM VIEW | MEMORY | 
| TABLES                                | SYSTEM VIEW | MEMORY | 
...
| appliance_info                        | BASE TABLE  | MyISAM | 
| cloud_appliance                       | BASE TABLE  | MyISAM | 
| cloud_config                          | BASE TABLE  | MyISAM |
| cloud_image                           | BASE TABLE  | MyISAM | 
| cloud_ipgroups                        | BASE TABLE  | MyISAM | 
| cloud_iplc                            | BASE TABLE  | MyISAM | 
| cloud_iptables                        | BASE TABLE  | MyISAM |
| cloud_irlc                            | BASE TABLE  | MyISAM |
| cloud_nat                             | BASE TABLE  | MyISAM | 
| cloud_private_image                   | BASE TABLE  | MyISAM | 
| cloud_requests                        | BASE TABLE  | MyISAM | 
| cloud_selector                        | BASE TABLE  | MyISAM | 
| cloud_transaction                     | BASE TABLE  | MyISAM | 
| cloud_users                           | BASE TABLE  | MyISAM | 
| cloud_users_limits                    | BASE TABLE  | MyISAM | 
| deployment_info                       | BASE TABLE  | MyISAM | 
...

Schema einer Tabelle anzeigen:

# echo "desc cloud_ipgroups;"|mysql -t -h localhost -uroot -p openqrm
+--------------+-------------+------+-----+---------+-------+
| Field        | Type        | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| ig_id        | int(5)      | YES  |     | NULL    |       | 
| ig_name      | varchar(50) | YES  |     | NULL    |       | 
| ig_network   | varchar(50) | YES  |     | NULL    |       | 
| ig_subnet    | varchar(50) | YES  |     | NULL    |       | 
| ig_gateway   | varchar(50) | YES  |     | NULL    |       | 
| ig_dns1      | varchar(50) | YES  |     | NULL    |       | 
| ig_dns2      | varchar(50) | YES  |     | NULL    |       | 
| ig_domain    | varchar(50) | YES  |     | NULL    |       | 
| ig_activeips | int(5)      | YES  |     | NULL    |       | 
+--------------+-------------+------+-----+---------+-------+
# echo "desc cloud_iptables;"|mysql -t -h localhost -uroot -p openqrm
+-----------------+-------------+------+-----+---------+-------+
| Field           | Type        | Null | Key | Default | Extra |
+-----------------+-------------+------+-----+---------+-------+
| ip_id           | int(5)      | YES  |     | NULL    |       | 
| ip_ig_id        | int(5)      | YES  |     | NULL    |       | 
| ip_appliance_id | int(5)      | YES  |     | NULL    |       | 
| ip_cr_id        | int(5)      | YES  |     | NULL    |       | 
| ip_active       | int(5)      | YES  |     | NULL    |       | 
| ip_address      | varchar(50) | YES  |     | NULL    |       | 
| ip_subnet       | varchar(50) | YES  |     | NULL    |       | 
| ip_gateway      | varchar(50) | YES  |     | NULL    |       | 
| ip_dns1         | varchar(50) | YES  |     | NULL    |       | 
| ip_dns2         | varchar(50) | YES  |     | NULL    |       | 
| ip_domain       | varchar(50) | YES  |     | NULL    |       | 
+-----------------+-------------+------+-----+---------+-------+

Zeitangaben in SQL

# echo "SELECT DATE_SUB(NOW(), INTERVAL 2 HOUR);" | mysql -t -h localhost -uroot -p
+---------------------------+
| (NOW() + INTERVAL 2 HOUR) |
+---------------------------+
| 2012-02-15 23:36:38       |
+---------------------------+

# echo "SELECT DATE_SUB(NOW(), INTERVAL 2 HOUR);" | mysql -t -h localhost -uroot -p
+----------------------------------+
| DATE_SUB(NOW(), INTERVAL 2 HOUR) |
+----------------------------------+
| 2012-02-15 19:36:41              |
+----------------------------------+

Heute:

# echo "SELECT DATE(NOW());" | mysql -t -h localhost -uroot -p
+-------------+
| DATE(NOW()) |
+-------------+
| 2012-03-12  |
+-------------+
# echo "SELECT CURDATE();" | mysql -t -h localhost -uroot -p
+------------+
| CURDATE()  |
+------------+
| 2012-03-12 |
+------------+

Gestern:

# echo "SELECT DATE(DATE_SUB(NOW(), INTERVAL 24 HOUR));" | mysql -t -h localhost -uroot -p
+-----------------------------------------+
| DATE(DATE_SUB(NOW(), INTERVAL 24 HOUR)) |
+-----------------------------------------+
| 2012-03-11                              |
+-----------------------------------------+
# echo "SELECT CURDATE() - interval 1 day;" | mysql -t -h localhost -uroot -p
+----------------------------+
| CURDATE() - interval 1 day |
+----------------------------+
| 2012-03-11                 |
+----------------------------+

Datenmenge bzw. Größe einer DB ausgeben

> echo "SELECT table_schema 'Datenbankname', sum( data_length + index_length ) / 1024 / 1024 'Datenbank in MB' FROM information_schema.tables GROUP BY table_schema;" | mysql -t
+--------------------+-----------------+
| Datenbankname      | Datenbank in MB |
+--------------------+-----------------+
| information_schema |      0.15625000 |
| mysql              |      2.41331005 |
| performance_schema |      0.00000000 |
| sys                |      0.01562500 |
| Syslog             |    201.51562500 |
+--------------------+-----------------+
> echo "SELECT table_schema 'Datenbankname', sum( data_length + index_length ) / 1024 / 1024 'Datenbank in MB',data_length / 1024 / 1024 'Daten in MB',index_length / 1024 / 1024 'Index in MB' FROM information_schema.tables GROUP BY table_schema;" | mysql -t
+--------------------+-----------------+--------------+-------------+
| Datenbankname      | Datenbank in MB | Daten in MB  | Index in MB |
+--------------------+-----------------+--------------+-------------+
| information_schema |      0.15625000 |   0.00000000 |  0.00000000 |
| mysql              |      2.41331005 |   0.00000000 |  0.00390625 |
| performance_schema |      0.00000000 |   0.00000000 |  0.00000000 |
| sys                |      0.01562500 |         NULL |        NULL |
| Syslog             |    201.51562500 | 201.50000000 |  0.00000000 |
+--------------------+-----------------+--------------+-------------+

gibt nur die komplette Summe (in MB) von allen Datenbanken aus:

> echo "SELECT table_schema, sum( data_length + index_length ) / 1024 / 1024 FROM information_schema.tables GROUP BY table_schema;" | mysql -N | awk '{z=$2;s+=z}END{print s,"MB"}'
204.101 MB

Datenmenge bzw. Größe einer Tabelle ausgeben

> echo "SELECT table_schema 'Datenbank', table_name 'Tabelle', sum( data_length + index_length ) / 1024 / 1024 'Gesamtgroesse in MB',data_length / 1024 / 1024 'Daten in MB',index_length / 1024 / 1024 'Index in MB' FROM information_schema.tables WHERE table_schema='Syslog' AND table_name='SystemEvents';" | mysql -t
+-----------+--------------+---------------------+--------------+-------------+
| Datenbank | Tabelle      | Gesamtgroesse in MB | Daten in MB  | Index in MB |
+-----------+--------------+---------------------+--------------+-------------+
| Syslog    | SystemEvents |        201.50000000 | 201.50000000 |  0.00000000 |
+-----------+--------------+---------------------+--------------+-------------+
#!/bin/bash
 
#------------------------------------------------------------------------------#
#
# Zeigt die Größe jeder einzelnen Tabelle einer Datenbank an.
# getestet mit MySQL Version 8.0.31
#
#------------------------------------------------------------------------------#
 
if [ "x${1}" = x ] ; then
        echo "${0} [Datenbankname]"
        echo "${0} simsysnetwork"
        echo "${0} simsysnetwork -N"
        exit 1
fi
 
if [ "x${2}" = "x-N" ] ; then
        OPT="-N"
        SQL="SELECT
        sum( data_length + index_length ) / 1024 / 1024 'Gesamtgroesse in MB',
        data_length / 1024 / 1024 'Daten in MB',
        index_length / 1024 / 1024 'Index in MB',
        table_schema 'Datenbank',
        table_name 'Tabelle'
        FROM information_schema.tables WHERE table_schema='${1}' AND"
else
        OPT="-t"
        SQL="SELECT
        table_schema 'Datenbank',
        table_name 'Tabelle', sum( data_length + index_length ) / 1024 / 1024 'Gesamtgroesse in MB',
        data_length / 1024 / 1024 'Daten in MB',
        index_length / 1024 / 1024 'Index in MB'
        FROM infor/root/bin/Tabellengröße_einer_Datenbank_anzeigen.sh simsysnetwork -Nmation_schema.tables WHERE table_schema='${1}' AND"
fi
 
for TAB in $(echo "SHOW TABLES;" | mysql -N ${1})
do
        echo "${SQL} table_name='${TAB}';" | mysql ${OPT}
done

Index

Die Regel sagt, dass man einen Index auf einer Tabelle dort braucht, wo man eine WHERE-Bedingung im Statement verwende.

Das heißt, das folgende SQL-Statement:

# SELECT * FROM Syslog.SystemEvents WHERE FromHost = 'fritz01' AND LEFT(ReceivedAt,10) = '2011-10-05' AND Facility = 1

benötigt einen Index auf den spalten "FromHost", "ReceivedAt" und "Facility".

Um die Tabelle entsprechend zu ändern, muss folgendes SQL-Statement abgesetzt werden:

# ALTER TABLE Syslog.SystemEvents ADD INDEX SearchIdx(Facility, FromHost, ReceivedAt);

damit wird ein einzener Index über die drei betreffenden spalten gelegt. Dann sollte man bei einer Abfrage immer alle drei Spalten als WHERE-Bedingung angeben!

Alternativ kann man auch jeweils einen einzelnen index pro spalte verwenden:

# ALTER TABLE Syslog.SystemEvents ADD INDEX facilityIdx(Facility), ADD INDEX fromHostIdx(FromHost), ADD INDEX receivedAt(ReceivedAt);

Das ist besser, wenn man nicht immer alle drei Spalten als WHERE-Bedingung angeben möchte.

Ein Index kann aber auch Nachteile haben: INSERT-Statements werden, mit steigender anzahl von Indizies, langsamer.

Man sollte es also nicht übertreiben und nur dort einen Index setzen, wo es wirklich nötig ist.

verweiste (orphan) Tabellen finden und beseitigen

verweiste Tabellen anzeigen:

> echo 'SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE "%#sql%";' | mysql -t

Aus der Ausgabe kann man den Datenbanknamen erkennen.

Da wir oftmals diese verweiste Tabelle nicht direkt löschen können, werden wir die Datenbank löschen. Vorher ist es aber ratsam, die heilen Tabellen vorübergehend woanders zwischen zu lagern.

Wen die Datenbank, in der die verweiste Tabelle erwartet wird "Syslog" heißt, dann geht man wie folgt vor:

> echo 'SELECT COUNT(*) FROM Syslog.SystemEvents;' | mysql -t
+----------+
| COUNT(*) |
+----------+
|   512946 |
+----------+

> echo 'USE Syslog; SHOW TABLES;' | mysql -t
+------------------------+
| Tables_in_Syslog       |
+------------------------+
| SystemEvents           |
| SystemEventsProperties |
+------------------------+

> echo 'CREATE DATABASE temp;' | mysql
> echo 'RENAME TABLE Syslog.SystemEvents TO temp.SystemEvents;' | mysql -t
> echo 'RENAME TABLE Syslog.SystemEventsProperties TO temp.SystemEventsProperties;' | mysql -t
> echo 'USE Syslog; SHOW TABLES;' | mysql -t
> echo 'USE temp; SHOW TABLES;' | mysql -t
+------------------------+
| Tables_in_Syslog       |
+------------------------+
| SystemEvents           |
| SystemEventsProperties |
+------------------------+

> echo 'DROP DATABASE Syslog;' | mysql
> echo 'CREATE DATABASE Syslog;' | mysql
> echo 'SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE "%#sql%";' | mysql -t
> echo 'RENAME TABLE temp.SystemEventsProperties TO Syslog.SystemEventsProperties;' | mysql -t
> echo 'RENAME TABLE temp.SystemEvents TO Syslog.SystemEvents;' | mysql -t
> echo 'USE temp; SHOW TABLES;' | mysql -t
> echo 'USE Syslog; SHOW TABLES;' | mysql -t
+------------------------+
| Tables_in_Syslog       |
+------------------------+
| SystemEvents           |
| SystemEventsProperties |
+------------------------+

> echo 'SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE "%#sql%";' | mysql -t
> echo 'DROP DATABASE temp;' | mysql
> echo 'SELECT COUNT(*) FROM Syslog.SystemEvents;' | mysql -t
+----------+
| COUNT(*) |
+----------+
|   512946 |
+----------+

MySQL Tuning

MySQL Tuning

Variablen/Einstellungen des DBMS:

SELECT * FROM sys.metrics;

Speicherplatzverbrauch:

SELECT * FROM sys.memory_global_total;
+-----------------+
| total_allocated |
+-----------------+
| 1.59 GiB        |
+-----------------+

wieviel Speicherplatz eine bestehende Verbindung verbraucht/belegt:

SELECT * FROM sys.host_summary;

wieviel Speicherplatz eine bestehende Verbindung für die einzelnen Tabellendateien verbraucht/belegt:

SELECT * FROM sys.host_summary_by_file_io_type;

hier kann man sogar Infos über einzelne Statements sehen:

SELECT * FROM sys.host_summary_by_statement_type;

hier, wieviele Daten gerade von einer Tabelle im RAM liegen:

SELECT * FROM sys.innodb_buffer_stats_by_schema;

…und diese ist bei Fehlersuche ganz wichtig, die sollte immer leer sein:

SELECT * FROM sys.innodb_lock_waits;

IO der einzelnen Tabellendateien im FS:

SELECT * FROM sys.io_global_by_file_by_bytes;

Zugriffswartezeiten je Tabellendatei:

SELECT * FROM sys.io_global_by_file_by_latency;

die Autoincrement-Werte für jede Tabelle:

SELECT * FROM sys.schema_auto_increment_columns;

Beispiel MySQL 8.0 mit 16 GiB RAM

Es sollten von der MySQL-DB nur max. 84% des RAM belegt werden.

innodb_buffer_pool_size + ( max_allowed_packet * max_connections ) <= 84% RAM

beide Konfigurationen belegen so ziehmlich die gleiche Menge RAM:

max_allowed_packet              = 16M
max_connections                 = 70
innodb_buffer_pool_size         = 12G

max_allowed_packet              = 64M
max_connections                 = 145
innodb_buffer_pool_size         = 4G
  1. Als erstes sollte man ermitteln, wie groß das benötigte "max_allowed_packet" sein muß.
    • Hier gilt die Regel, nur so groß wie nötig aber so klein wie möglich.
  2. Als zweites sollte man ermitteln, wieviele Verbindungen maximal zur Datenbank gleichzeitig gehalten werden sollen (max_connections).
    • Hier gilt die Regel, nur soviele wie nötig aber sowenig wie möglich.
  3. Als letztes kann man dann damit errechnen, wieviel Speicher noch für den "innodb_buffer_pool_size" zur verfügung steht:
    • "RAM" * 0,84 - ( max_allowed_packet * max_connections ) = innodb_buffer_pool_size
    • 16384MB * 0,84 - ( 16M * 70 ) = 12642,56 ~ 12GB
    • 16384MB * 0,84 - ( 64M * 145 ) = 4482,56 ~ 4GB
max_allowed_packet auf 128 MB setzen:
> echo "SET GLOBAL max_connections=300; SET GLOBAL max_allowed_packet=$((128*1024*1024));" | mysql -t
> echo "SHOW VARIABLES LIKE 'innodb_buffer_pool_size'; SHOW VARIABLES LIKE 'max_allowed_packet'; SHOW VARIABLES LIKE 'max_connections';" | mysql -t
+-------------------------+-------------+
| Variable_name           | Value       |
+-------------------------+-------------+
| innodb_buffer_pool_size | 16106127360 |
+-------------------------+-------------+
+--------------------+-----------+
| Variable_name      | Value     |
+--------------------+-----------+
| max_allowed_packet | 134217728 |
+--------------------+-----------+
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections | 300   |
+-----------------+-------+
alle Infos von jeder einzelnen Tabelle aus dem gesamten DBMS anzeigen:
> for A in $(echo "USE information_schema; SHOW TABLES;" | mysql -N); do echo "# SELECT * FROM information_schema.${A};"; echo "SELECT * FROM information_schema.${A};" | mysql -t ; done

alle Einstellungen von jeder einzelnen Tabelle aus dem gesamten DBMS anzeigen:
> for A in $(echo "USE performance_schema; SHOW TABLES;" | mysql -N); do echo "# SELECT * FROM performance_schema.${A};"; echo "SELECT * FROM performance_schema.${A};" | mysql -t ; done

Speicherplatz (und weitere Infos) von jeder einzelnen Tabelle aus dem gesamten DBMS anzeigen:
> for A in $(echo "USE sys; SHOW TABLES;" | mysql -N); do echo "# SELECT * FROM sys.${A};"; echo "SELECT * FROM sys.${A};" | mysql -t ; done

Beispiel MySQL 8.0 mit 32 GiB RAM

# echo "SHOW VARIABLES LIKE 'innodb_buffer_pool_size'; SHOW VARIABLES LIKE 'max_allowed_packet'; SHOW VARIABLES LIKE 'max_connections';" | mysql -t
+-------------------------+------------+
| Variable_name           | Value      |
+-------------------------+------------+
| innodb_buffer_pool_size | 1073741824 |
+-------------------------+------------+
+--------------------+-----------+
| Variable_name      | Value     |
+--------------------+-----------+
| max_allowed_packet | 268435456 |
+--------------------+-----------+
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections | 100   |
+-----------------+-------+

# echo "SHOW VARIABLES LIKE 'innodb_buffer_pool_size'; SHOW VARIABLES LIKE 'max_allowed_packet'; SHOW VARIABLES LIKE 'max_connections';" | mysql -N | awk '{print $NF}' | tr -s '\n' ' ' | awk '{a=($1 + ($2 * $3)) / 1024^3; print a,"GiB /",a*100/84,"GiB"}'
26 GiB / 30.9524 GiB

# echo "1024 256 100" | awk '{a=($1 + ($2 * $3))/1024; print a,"GiB /",a*100/84,"GiB"}'
26 GiB / 30.9524 GiB

oder auch so möglich:

# echo "1024 128 200" | awk '{a=($1 + ($2 * $3))/1024; print a,"GiB /",a*100/84,"GiB"}'
26 GiB / 30.9524 GiB

Fehlermeldungen

ERROR 2006 (HY000) at line 13135: MySQL server has gone away

Diesen Fehler bekommt man gelegentlich, wenn man einen Dump einspielt. Im Internet findet man verschiedenen Lösungsvorschläge, die vereinzelt auch funktionieren. Hier alle Anpassungen, die ich dazu gefunden habe.

/etc/mysql/mariadb.conf.d/99-basic_common.cnf
[mysqld]
### mehr als 1G gehen nicht
max_allowed_packet             = 1G
### mehr als 1G gehen nicht
net_buffer_length              = 1G
net_read_timeout               = 28800
innodb_lock_wait_timeout       = 28800
delayed_insert_timeout         = 28800
connect_timeout                = 28800
wait_timeout                   = 28800

Allerdings funktioniert es nicht immer.

Start eines 2. MySQL-DBMS

Dirty Start

#!/bin/bash
 
(/bin/sh /usr/bin/mysqld_safe --defaults-file=/etc/mysql/my1.cnf) &
 
sleep 3
set -x
ps alxwww | grep -Fi mysql | grep -F port=3307
netstat -antpwww | grep -F :3307
mysqlshow -S /var/lib/mysql/data1/mysqld.sock
wc -l /var/lib/mysql/mysqlerr1.log

EVENTS + ROUTINES

alle Proceduren anzeigen:

SELECT SPECIFIC_NAME,ROUTINE_SCHEMA,ROUTINE_NAME,ROUTINE_TYPE FROM information_schema.routines WHERE ROUTINE_SCHEMA!='sys';

alle Events anzeigen:

USE Datenbankname;
SHOW EVENTS;

einen Event auf einem Knoten aktivieren:

ALTER EVENT Eventname ON SCHEDULE EVERY 1 MINUTE ON COMPLETION PRESERVE ENABLE;
/home/http/wiki/data/attic/mysql.1718716793.txt · Zuletzt geändert: von manfred