VorwortWenn in einer tatsächlichen Produktionsumgebung sowohl das Lesen als auch das Schreiben in eine MySQL-Datenbank in einem Datenbankdienst ausgeführt wird, kann dies die tatsächlichen Anforderungen in Bezug auf Sicherheit, hohe Verfügbarkeit und hohe Parallelität nicht erfüllen. Im Allgemeinen werden Daten durch Master-Slave-Replikation synchronisiert, und dann wird eine Lese-/Schreibtrennung verwendet, um die gleichzeitige Ladekapazität der Datenbank zu verbessern. 1. MySQL Master-Slave-Replikation1. Unterstützte ReplikationstypenAnweisungsbasierte Replikation (Anweisung): Führen Sie SQL-Anweisungen auf dem Server aus und führen Sie dieselben Anweisungen auf dem Slave-Server aus. MySQL verwendet standardmäßig eine anweisungsbasierte Replikation, die eine hohe Ausführungseffizienz aufweist. Zeilenbasierte Replikation (Zeile): Kopieren Sie den geänderten Inhalt, anstatt den Befehl auf dem Slave-Server auszuführen. Gemischte Replikation (gemischt): Führen Sie SQL-Anweisungen auf dem Server aus und führen Sie dieselben Anweisungen auf dem Slave-Server aus. MySQL verwendet standardmäßig eine anweisungsbasierte Replikation, die eine hohe Ausführungseffizienz aufweist. 2. Der Arbeitsprozess der Master-Slave-Replikation basiert auf ProtokollenMaster-Binärprotokoll Slave-Relay-Protokoll 3. AnfragemethodeE/A-Threads Thread löschen SQL-Thread 4. Das Prinzip der Master-Slave-Replikation①Der Masterknoten zeichnet Datenänderungen in einem Binärprotokoll auf. Wenn sich die Daten auf dem Masterknoten ändern, werden die Änderungen in das Binärprotokoll geschrieben. ②Der Slave-Knoten erkennt in einem bestimmten Zeitintervall, ob sich das Binärprotokoll des Masters geändert hat. Tritt eine Änderung auf, wird ein I/O-Thread gestartet, der das binäre Ereignis des Masters anfordert. ③Gleichzeitig startet der Master-Knoten für jeden I/O-Thread einen Dump-Thread, um ihm binäre Ereignisse zu senden und sie im lokalen Relay-Protokoll des Slave-Knotens zu speichern. ④Der Slave-Knoten startet den SQL-Thread, um das Binärprotokoll aus dem Relay-Protokoll zu lesen und es lokal wiederzugeben, d. h., er analysiert es in SQL-Anweisungen und führt sie nacheinander aus, um seine Daten mit denen des Master-Knotens in Einklang zu bringen. Schließlich wechseln der E/A-Thread und der SQL-Thread in einen Ruhezustand und warten darauf, beim nächsten Mal aufgeweckt zu werden. Der Replikationsprozess weist eine wichtige Einschränkung auf: Die Replikation erfolgt auf dem Slave serialisiert, was bedeutet, dass parallele Aktualisierungsvorgänge auf dem Master nicht parallel auf dem Slave ausgeführt werden können. Relay-Protokolle befinden sich normalerweise im Betriebssystem-Cache, daher ist der Overhead durch Relay-Protokolle sehr gering. 5. Für welche Szenarien eignen sich MySQL-Cluster und Master-Slave-Replikation?Clustering und Master-Slave-Replikation sind darauf ausgelegt, mit hoher Parallelität und großem Datenverkehr fertig zu werden. Wenn der Datenverkehr und die Parallelität einer Website zu groß sind, kann eine kleine Anzahl von Datenbankservern dies nicht bewältigen, was zu langsamen Websitezugriffen führt. Das Schreiben von Daten führt dazu, dass die Datentabelle oder der Datensatz gesperrt wird. Sperren bedeutet, dass andere Zugriffsthreads vorübergehend nicht lesen oder schreiben können und warten müssen, bis der Schreibvorgang abgeschlossen ist, bevor sie fortfahren können, was die Lesegeschwindigkeit anderer Benutzer beeinträchtigt. Die Verwendung der Master-Slave-Replikation kann dieses Problem lösen, indem einige Server auf das Lesen und andere auf das Schreiben spezialisiert werden. 6. Warum Master-Slave-Replikation und Lese-/Schreibtrennung verwenden?Master-Slave-Replikation und Lese-/Schreibtrennung werden im Allgemeinen zusammen verwendet. Der Zweck ist sehr einfach: Er besteht darin, die parallele Leistung der Datenbank zu verbessern. Sie können sich vorstellen, dass die Leistung definitiv nicht hoch sein wird, wenn es sich um eine einzelne Maschine handelt und sowohl das Lesen als auch das Schreiben auf einem MySQL erfolgt. Wenn es drei MySQL-Server gibt, von denen ein Master nur für Schreibvorgänge und zwei Slaves nur für Lesevorgänge zuständig sind, würde sich die Leistung dann nicht erheblich verbessern? Daher sollen Master-Slave-Replikation und Lese-/Schreibtrennung es der Datenbank ermöglichen, eine höhere Parallelität zu unterstützen. Wenn MySQL mit zunehmendem Geschäftsvolumen auf einer einzelnen Maschine bereitgestellt wird, ist die E/A-Frequenz zu hoch. Durch die Verwendung von Master-Slave-Replikation und Lese-/Schreibtrennung kann die Verfügbarkeit der Datenbank verbessert werden 7. Zweck und BedingungenMySQL Master-Slave-Replikationszwecke: Notfallwiederherstellung in Echtzeit für Failover Trennung von Lesen und Schreiben, Bereitstellung von Abfragediensten Backup, um Beeinträchtigungen der Dienste zu vermeiden Notwendige Voraussetzungen: Die Hauptdatenbank öffnet das Binlog-Protokoll (Log-Bin-Parameter festlegen) Die Master- und Slave-Server-IDs sind unterschiedlich Der Slave-Server kann sich mit dem Master verbinden 8. Probleme mit der MySQL Master-Slave-ReplikationNach dem Ausfall der Hauptdatenbank können Daten verloren gehen Die Slave-Datenbank verfügt nur über einen SQL-Thread, die Master-Datenbank hat einen hohen Schreibdruck und die Replikation wird wahrscheinlich verzögert Lösung Halbsynchrone Replikation – Lösung für das Problem des Datenverlusts Parallele Replikation - Lösung des Problems der Verzögerung bei der Slave-Replikation 9. Verzögerung der MySQL-Master-Slave-Replikation ①Hohe Parallelität des Masterservers, was zu einer großen Anzahl von Transaktionen führt ②Netzwerkverzögerung ③Master-Slave-Hardwaregeräte - CPU-Hauptfrequenz, Speicher-E/A, Festplatten-E/A
2. Master-Slave-Replikation3. Lese- und Schreibtrennung1. Grundsatz①Schreiben Sie nur auf dem Master-Server und lesen Sie nur auf dem Slave-Server ②Die Master-Datenbank verarbeitet Transaktionsabfragen und die Slave-Datenbank verarbeitet Auswahlabfragen ③Die Datenbankreplikation wird verwendet, um Änderungen, die durch Transaktionsabfragen verursacht werden, an Slave-Datenbanken im Cluster zu synchronisieren 2. Warum müssen wir Lesen und Schreiben trennen?Denn der „Schreib“-Vorgang der Datenbank (das Schreiben von 10.000 Daten kann 3 Minuten dauern) ist relativ zeitaufwändig, der „Lese“-Vorgang der Datenbank (das Lesen von 10.000 Daten kann jedoch nur 5 Sekunden dauern), sodass die Trennung von Lesen und Schreiben das Problem löst, dass das Schreiben in die Datenbank die Effizienz der Abfrage beeinträchtigt. 3. Wann sollten Lesen und Schreiben getrennt werden?Die Datenbank muss nicht unbedingt vom Lesen und Schreiben getrennt werden. Wenn das Programm die Datenbank häufiger verwendet, aber weniger aktualisiert und häufiger abfragt, sollten wir die Verwendung der Datenbank-Master-Slave-Synchronisierung in Betracht ziehen. Durch die Trennung von Lesen und Schreiben kann der Datenbankdruck dann geteilt und die Leistung verbessert werden. 4. Master-Slave-Replikation und Trennung von Lesen und Schreiben In der tatsächlichen Produktionsumgebung erfolgen das Lesen und Schreiben der Datenbank alle auf demselben Datenbankserver, was den tatsächlichen Anforderungen nicht gerecht wird. 5. Derzeit gängigere MySQL-Lese-/SchreibtrennungUnterteilt in die folgenden zwei Typen ① Basierend auf der internen Implementierung des Programmcodes Im Code werden Routen nach Auswahl und Einfügen klassifiziert. Diese Methode wird auch in Produktionsumgebungen am häufigsten verwendet. Der Vorteil besteht darin, dass die Leistung besser ist, da sie im Programmcode implementiert ist und keine zusätzlichen Geräte für Hardwarekosten erforderlich sind. Der Nachteil besteht darin, dass Entwickler für die Implementierung erforderlich sind und das Betriebs- und Wartungspersonal keine Ahnung hat, wo es anfangen soll. Allerdings sind nicht alle Anwendungen für die Implementierung einer Lese-/Schreibtrennung im Programmcode geeignet. Beispielsweise erfordern einige große und komplexe Java-Anwendungen eine große Codeänderung, wenn eine Lese-/Schreibtrennung im Programmcode implementiert wird. ② Implementierung basierend auf der Zwischenproxyschicht Der Proxy befindet sich normalerweise zwischen dem Client und dem Server. Nach Erhalt der Clientanforderung leitet der Proxyserver sie nach der Beurteilung an die Backend-Datenbank weiter. Die folgenden sind repräsentative Programme: (1) MySQL-Proxy. MySQL-Proxy ist ein MySQL-Open-Source-Projekt, das SQL-Beurteilungen über ein eigenes Lua-Skript durchführt. Da die Verwendung von MySQL Proxy das Schreiben vieler Lua-Skripte erfordert, sind diese Lua-Skripte nicht vorgefertigt, sondern müssen von Ihnen selbst geschrieben werden, was für Personen, die mit den integrierten Variablen von MySQL Proxy und dem MySQL-Protokoll nicht vertraut sind, sehr schwierig ist. IV. Fallumsetzung1. FallumgebungDiese Fallumgebung wird mithilfe des Stage-Servers erstellt. Das Topologiediagramm sieht wie folgt aus
2. Experimentelle Ideen (Bedürfnisse lösen)Clientzugriffs-Proxyserver Proxy-Server schreibt auf den Master-Server Der Master-Server schreibt Ergänzungen, Löschungen und Änderungen in sein eigenes Binärprotokoll Der Slave-Server synchronisiert das Binärprotokoll des Master-Servers mit seinem eigenen Relay-Protokoll. Wiedergeben von Relay-Protokollen vom Server in die Datenbank Der Client liest, dann greift der Proxy-Server direkt auf den Slave-Server zu Reduzieren Sie die Last und übernehmen Sie eine Lastausgleichsfunktion 3. Vorbereitung
systemctl stoppe Firewall systemctl deaktiviert Firewall #Firewall ausschalten (und beim Start deaktivieren) 0 #Deaktivieren Sie den Sicherheitszugriffskontrollmechanismus 4. Erstellen Sie eine MySQL-Master-Slave-Replikation①MySQL-Master-Slave-Server-Zeitsynchronisierung Master-Server-Einstellungen #NTP installieren yum -y installiere NTP #NTP konfigurieren vim /etc/ntp.conf #Fügen Sie der letzten Zeile den folgenden Inhalt hinzu: Server 127.127.126.0 Fudge 127.127.126.0 Schicht 8 #Stellen Sie die lokale Taktquelle ein und achten Sie darauf, das Netzwerksegment zu ändern. #Stellen Sie die Zeitstufe auf 8 ein (begrenzt auf 15). #Dienst neu starten Dienst ntpd neu starten Aus den Servereinstellungen yum -y installiere NTP ntpdate #Dienst installieren, ntpdate wird zum Synchronisieren der Zeit verwendet, die der Dienst ntpd startet #Starten Sie den Dienst /usr/sbin/ntpdate 192.168.126.11 #Führen Sie eine Zeitsynchronisierung durch und verweisen Sie auf die IP des Master-Servers crontab -e #Schreiben Sie eine geplante Aufgabe, um die Zeit jede halbe Stunde zu synchronisieren*/30 * * * * /usr/sbin/ntpdate 192.168.126.11 ②MySQL-Masterserver konfigurieren vim /etc/meine.cnf #Konfigurieren Sie den folgenden Inhalt Server-ID = 1 log-bin=master-bin #Hinzufügen, Master-Server öffnet Binärprotokoll log-slave-updates=true #Hinzufügen, Aktualisierung des Binärprotokolls vom Server zulassen systemctl restart mysqld #Starten Sie den Dienst neu, damit die Konfiguration wirksam wird mysql -uroot -p123123 #Melden Sie sich beim Datenbankprogramm an und erteilen Sie dem Slave-Server die Autorisierung. GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'192.168.126.%' IDENTIFIED BY '123123'; FLUSH-PRIVILEGIEN; Masterstatus anzeigen; aufhören #Die Spalte „Datei“ zeigt den Protokollnamen und die Spalte „Position“ den Offset ③Konfigurieren Sie den Slave-Server vim /etc/meine.cnf Server-ID = 2 #Ändern, beachten Sie, dass sich die ID von der des Masters unterscheidet und die IDs der beiden Slaves ebenfalls unterschiedlich sein müssen relay-log=relay-log-bin #Relay-Protokoll hinzufügen, öffnen, Protokolldateidatensätze vom Masterserver mit dem lokalen Relay-Log-Index = Slave-Relay-bin.index synchronisieren #Hinzufügen, Speicherort und Name der Relay-Protokolldatei definieren systemctl restart mysqld mysql -uroot -p123123 Ändere den Master in master_host='192.168.126.11', master_user='myslave',master_password='123123',master_log_file='master-bin.000001',master_log_pos=604; #Synchronisierung konfigurieren. Beachten Sie, dass die Werte von master_log_file und master_log_pos mit denen des Master-Start-Slaves übereinstimmen müssen. #Synchronisierung starten, bei Fehler „Slave zurücksetzen“ ausführen; Slave-Status anzeigen\G #Überprüfen Sie den Slave-Status // Stellen Sie sicher, dass sowohl IO- als auch SQL-Threads Ja sind, was darauf hinweist, dass die Synchronisierung normal ist Slave_IO_Running: Ja #Verantwortlich für die E/A-Kommunikation mit dem Host Slave_SQL_Running: Ja #Verantwortlich für Ihren eigenen Slave-MySQL-Prozess Sklave1: Slave2: Gleiche Konfiguration wie Slave1, aber andere IDs Generell gibt es mehrere Möglichkeiten für Slave_IO_Running: Nein:
④Überprüfen Sie den Master-Slave-Replikationseffekt 5. Erstellen Sie eine MySQL-Lese-/Schreibtrennung
① Installieren Sie die Java-Umgebung auf dem Host Amoeba. Da Amoeba auf Basis von jdk1.5 entwickelt wurde, wird offiziell empfohlen, jdk1.5 oder 1.6 zu verwenden. Höhere Versionen werden nicht empfohlen. cd /opt/ #Ziehen Sie in FinalShell das Softwarepaket amoeba-mysql-binary-2.2.0.tar.gz hinein jdk-6u14-linux-x64.bin cp jdk-6u14-linux-x64.bin /usr/local/ cd /usr/lokal/ chmod +x jdk-6u14-linux-x64.bin ./jdk-6u14-linux-x64.bin #Halten Sie die Eingabetaste gedrückt, bis Sie das Ende erreicht haben. Geben Sie bei der entsprechenden Aufforderung „YES“ ein und drücken Sie die Eingabetaste. mv jdk1.6.0_14/ /usr/local/jdk1.6 #vim /etc/profile umbenennen #Bearbeiten Sie die globale Konfigurationsdatei und fügen Sie in der letzten Zeile die folgende Konfiguration hinzu: export JAVA_HOME=/usr/local/jdk1.6 export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib export PATH=$JAVA_HOME/lib:$JAVA_HOME/jre/bin/:$PATH:$HOME/bin export AMOEBA_HOME=/usr/local/amoeba export PATH=$PATH:$AMOEBA_HOME/bin #Ausgabe definiert das Java-Arbeitsverzeichnis #Gibt den angegebenen Java-Typ aus #Fügt Java zur Pfadumgebungsvariablen hinzu #Ausgabe definiert das Amöben-Arbeitsverzeichnis #Fügt die Pfadumgebungsvariable source /etc/profile hinzu #Führen Sie die geänderte globale Konfigurationsdatei java -version aus #Überprüfen Sie die Java-Versionsinformationen, um zu überprüfen, ob die Installation erfolgreich war ②Installieren und konfigurieren Sie Amoeba mkdir /usr/local/amoeba tar zxvf /opt/amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/ chmod -R 755 /usr/local/amoeba/ /usr/local/amoeba/bin/amoeba #Wenn amoeba start|stop angezeigt wird, bedeutet dies, dass die Installation erfolgreich war ③Konfigurieren Sie die Lese-/Schreibtrennung von Amowba und den Lese- und Schreiblastausgleich für zwei Slaves. Öffnen Sie die Berechtigungen für Amoeba, um auf MySQL von Master, Slave1 und Slave2 zuzugreifen. ④Bearbeiten Sie die Konfigurationsdatei amoeba.xml im Host amoeba cd /usr/local/amoeba/conf/ cp amoeba.xml amoeba.xml.bak vim amoeba.xml #Ändern Sie die Amoeba-Konfigurationsdatei. #Ändern Sie Zeile 30 <property name="user">amoeba</property> #Ändern Sie Zeile 32 <property name="password">123123</property> #115 Zeilenänderung <property name="defaultPool">master</property> #117 Entfernen Sie den Kommentar <property name="writePool">master</property> <Eigenschaftsname="readPool">Sklaven</Eigenschaft> ⑤Bearbeiten Sie die Konfigurationsdatei dbServers.xml cp dbServers.xml dbServers.xml.bak vim dbServers.xml #Ändern Sie die Datenbankkonfigurationsdatei. Zeile 23 auskommentieren. Zweck: Geben Sie standardmäßig die Testbibliothek ein. Falls in MySQL keine Testbibliothek vorhanden ist, wird ein Fehler gemeldet. <!-- <property name="schema">test</property> --> #26 Zeilenänderung <property name="user">test</property> #28-30 Zeilen kommentieren <property name="password">123.com</property> aus #Ändern Sie Zeile 45 und setzen Sie den Namen des Masterservers auf Master <dbServer name="master" parent="abstractServer"> #Ändern Sie Zeile 48 und legen Sie die Adresse des primären Servers fest <property name="ipAddress">192.168.126.11</property> #Ändern Sie Zeile 52 und setzen Sie den Namen des Slave-Servers auf Slave1 <dbServer name="slave1" parent="abstractServer"> #Ändern Sie Zeile 55 und legen Sie die Adresse des Slave-Servers 1 fest <property name="ipAddress">192.168.126.13</property> #58 Kopieren und fügen Sie die obigen 6 Zeilen ein, um den Namen und die Adresse des Slave-Servers 2 festzulegen <dbServer name="slave2" parent="abstractServer"> <Eigenschaftsname="IP-Adresse">192.168.184.14</Eigenschaft> #65 Zeilenänderung <dbServer name="slaves" virtual="true"> #71 Ändern Sie <property name="poolNames">slave1,slave2</property> ⑥Nachdem Sie bestätigt haben, dass die Konfiguration korrekt ist, können Sie die Amoeba-Software starten. Der Standardport ist TCP 8066 /usr/local/amoeba/bin/amoeba start& #Starten Sie die Amoeba-Software und drücken Sie Strg+C, um zu netstat -anpt | grep java zurückzukehren. #Überprüfen Sie, ob Port 8066 geöffnet ist. Der Standardport ist TCP 8066 ⑦Prüfung 1. Gehen Sie zum Client und installieren Sie schnell den virtuellen MySQL-Client. Greifen Sie dann über den Proxy auf MySQL zu yum -y installiere MySQL #Verwenden Sie YUM, um den virtuellen MySQL-Client schnell zu installieren mysql -u amoeba -p123123 -h 192.168.126.12 -P8066 #Greifen Sie über den Proxy auf MySQL zu, die IP-Adresse zeigt auf Amoba #Nachdem über den Client eine Verbindung zu MySQL hergestellt wurde, werden die geschriebenen Daten nur vom Master-Dienst aufgezeichnet und dann mit dem Slave-Server synchronisiert 2. Erstellen Sie eine Tabelle auf dem Master und synchronisieren Sie diese mit den beiden Slave-Servern Club benutzen; Tabelle erstellen puxin (id int(10),name varchar(10),adresse varchar(20)); 3. Schalten Sie dann die Slave-Funktion des Slave-Servers aus, synchronisieren Sie die Tabelle vom Master-Server und fügen Sie den Dateninhalt manuell ein Sklave stoppen; #Synchronisierung ausschalten, Club verwenden; in Puxin-Werte einfügen('1', 'wangyi', 'this_is_slave1'); #Sklave2 in Puxin-Werte einfügen('2', 'wanger', 'this_is_slave2'); 4. Kehren Sie zum Hauptserver zurück und fügen Sie weitere Inhalte ein in Pucin-Werte einfügen ('3', 'Wangwu', 'this_is_master'); 5. Testen Sie den Lesevorgang und gehen Sie zum Client-Host, um die Ergebnisse abzufragen Club verwenden; wähle * aus Puxin; 6. Auf dem Client wird eine Anweisung eingefügt, die jedoch auf dem Client nicht abgefragt werden kann. Schließlich kann der Inhalt dieser Anweisung nur auf dem Master angezeigt werden, was darauf hinweist, dass der Schreibvorgang auf dem Master-Server erfolgt. in Puxin-Werte einfügen ('4', 'liuliu', 'this_is_client'); 7. Führen Sie dann „Start Slave“ auf den beiden Slave-Servern aus. Die auf dem Master-Server hinzugefügten Daten können synchronisiert werden. ZusammenfassenDadurch wird bestätigt, dass die Lese- und Schreibtrennung von MySQL erreicht wurde. Derzeit werden alle Schreibvorgänge auf dem Masterserver ausgeführt, um Datenasynchronität zu vermeiden. Um die Belastung der Datenbank zu verteilen, werden alle Lesevorgänge auf den Slave-Server verteilt. 1. So überprüfen Sie, ob der Master-Slave-Synchronisierungsstatus erfolgreich istGeben Sie den Befehl „show slave status\G“ im Slave-Server ein, um die Master-Slave-Informationen anzuzeigen, die die Statusinformationen des IO-Threads sowie die IP-Adresse, den Port und die Transaktionsstartnummer des Master-Servers enthalten. Wenn bei „slave_io_running“ und „slave_sql_running“ beide „Ja“ angezeigt wird, bedeutet dies, dass der Master-Slave-Synchronisierungsstatus erfolgreich ist. 2. Wenn E/A und SQL nicht „Ja“ sind, wie beheben Sie das Problem?
3. Welche Informationen können in der Anzeige des Slave-Status angezeigt werden (wichtiger)
4. Was sind die möglichen Gründe für eine langsame Master-Slave-Replikation (Verzögerung)?
Oben finden Sie den ausführlichen Inhalt des intensiven Tutorials zur Master-Slave-Replikation und Lese-/Schreibtrennung von MySQL-Datenbanken. Weitere Informationen zur Master-Slave-Replikation und Lese-/Schreibtrennung von MySQL-Datenbanken finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM! Das könnte Sie auch interessieren:
|
<<: HTML zur Erzielung einer dynamischen Anzeige des Farbblockberichtseffekts (Beispielcode)
>>: Centos8 erstellt NFS basierend auf KDC-Verschlüsselung
Empfohlene Docker-Lernmaterialien: https://www.ru...
Wenn der Pfad nach dem Domänennamen auf andere Ve...
/******************** * Virtuelles Dateisystem VF...
Sttty ist ein gängiger Befehl zum Ändern und Druc...
<br />Gestalten Sie Ihre Website wissenschaf...
1. Übersicht über SQLException Wenn bei der Verwe...
1. Das Schlüsselwort as gibt eine Behauptung an I...
Obwohl Kopf und DTD nicht auf der Seite angezeigt...
1. Aktualisieren Sie die gesamte Tabelle. Wenn de...
Das Löschen einer Tabelle in MySQL ist sehr einfa...
<br />Welche Grundsätze sollten beachtet wer...
Eine MySQL-ähnliche PHP-Switch-Case-Anweisung. wä...
Manchmal möchten Sie eine App testen, aber nicht ...
Vorwort Wie wir alle wissen, ist „Wie zentriert m...
Wie der Titel schon sagt, kann andernfalls bei ein...