Heim  >  Artikel  >  Datenbank  >  Welche Wissenspunkte gibt es im Zusammenhang mit Java- und MySQL-Sperren?

Welche Wissenspunkte gibt es im Zusammenhang mit Java- und MySQL-Sperren?

王林
王林nach vorne
2023-05-27 10:18:171030Durchsuche

    Definition von Sperre

    In Computerprogrammen werden Sperren für exklusive Ressourcen verwendet. Erst wenn die Sperre erhalten wird, können die entsprechende Ressourcen betrieben werden.

    Implementierung der Sperre

    Die Implementierung der Sperre am unteren Rand des Computers basiert auf den von der CPU bereitgestellten CAS-Anweisungen für eine Speicheradresse vergleicht den ursprünglichen Wert und versucht, den Wert zu ändern. Ob der Wert erfolgreich geändert wurde, zeigt an, ob die Sperre ergriffen wurde.

    Sperren in JVM

    Es gibt 2 häufig verwendete Sperren in JVM

    synchronisiert

    synchronisiert wird von Java bereitgestellt Die Schlüsselwortsperre kann Objekte, Klassen und Methoden sperren.
    Nach JDK1.6 wurde die Synchronisierung optimiert und die voreingenommene Sperre und der Lightweight-Sperrmodus wurden wie folgt hinzugefügt:

    • #🎜🎜 # Beim ersten Sperren wird eine Bias-Sperre hinzugefügt, d. Dieser Modus verbessert den Durchsatz eines einzelnen Threads erheblich, der wiederholt dieselbe Sperre erhält. Laut Java-Beamten treten die meisten Sperrkonflikte im selben Thread auf.

      Wenn die CAS-Erfassung der Bias-Sperre fehlschlägt, bedeutet dies, dass sich der aktuelle Thread von dem Thread unterscheidet, der durch die Bias-Sperre voreingenommen ist, und die Bias-Sperre
    • Aktualisieren Sie
    • auf ein leichtes Schloss. Das Merkmal eines leichten Schlosses besteht darin, das Schloss über

      spinCAS zu erhalten.

      Wenn die Spin-Erfassung fehlschlägt, wird die Sperre auf eine Gewichtssperre aktualisiert und alle Threads, die auf die Sperre warten, werden von der JVM angehalten Nach der Freigabe wacht die JVM mit einer einheitlichen Benachrichtigung auf und versucht erneut, die CAS-Sperre durchzuführen. Wenn dies fehlschlägt, bleibt sie hängen.
    • Der Zweck des voreingenommenen Sperrendesigns besteht offensichtlich darin, dass „aus der offiziellen Java-Perspektive die meisten Konflikte um dieselbe Sperre im selben Thread auftreten.“
    • Der Zweck des leichten Sperrendesigns besteht darin, dass „kurzfristig Sperrenkonflikte durch Spin-CAS erzielt werden können und der CPU-Spin-Verbrauch in kurzer Zeit geringer ist als der Verbrauch beim Anhalten und Wiedererwecken von Threads.“
    Die Gewichtssperre ist die synchronisierte Logik vor der anfänglichen Optimierung.


    ReentrantLock

    Apropos ReentrantLock, wir müssen über AQS in JUC sprechen.

    Der vollständige Name von AQS lautet AbstractQueueSynchronizer. Fast alle Toolklassen in JUC verlassen sich bei der Implementierung auf AQS.

    AQS ist eine abstrakte Klasse in Java, aber im Wesentlichen handelt es sich um die Implementierung einer Idee in Java.

    Die Implementierungslogik von AQS lautet wie folgt:


    Eine Warteschlange erstellen
    • Wartung in Die Warteschlange erfordert Warten. Der Sperrthread
    • Der Hauptknoten ist immer der Knoten, der die Sperre (oder die Ressource) hält, und die wartenden Knoten werden nacheinander nacheinander verbunden Kopfknoten.
    • Nachdem der Hauptknoten die Sperre aufgehoben hat, werden die wartenden Knoten der Reihe nach aufgeweckt, und diese Knoten werden dann erneut versuchen, die Sperre zu erhalten.
    • Nach der Optimierung der synchronisierten Sperre unterscheidet sich das Wesen von AQS nicht wesentlich vom synchronisierten, und die Leistung der beiden unterscheidet sich nicht wesentlich, daher die aktuellen Eigenschaften von AQS Ja:

    ist eine auf der Java-API-Ebene implementierte Sperre, sodass verschiedene gleichzeitige Toolklassen implementiert werden können und die Bedienung flexibler ist
      #🎜🎜 ##🎜 🎜#
    • Da es Mechanismen wie Timeout und flexiblen Betrieb bietet, ist es nicht anfällig für Deadlocks. Wenn ein Deadlock auftritt, wird die Fehlerbehebung schwieriger, da jstack keinen Deadlock-Indikator anzeigt.

    • kann eine faire Sperre erreichen, synchronisiert muss jedoch eine unfaire Sperre sein.

    • Da es sich um eine von der JavaApi-Schicht implementierte Sperre handelt, kann sie auf Interrupts reagieren.

    • An diesem Punkt werden Sie feststellen, dass ReentrantLock tatsächlich als Implementierung von synchronisiert in der JavaApi-Ebene bezeichnet werden kann.

      MySQL-Sperre
    Gemeinsame Sperre (S) und exklusive Sperre (X)

    Geltungsbereich

    Diese beiden Alle Typen Zu den Sperren gehören Sperren auf Zeilenebene und Sperren auf Tabellenebene.

    Wenn beim Erwerb einer gemeinsamen Sperre die Daten durch die exklusive Sperre einer anderen Transaktion gesperrt sind, können sie nicht erworben werden und müssen auf die Freigabe der exklusiven Sperre warten.

    Absichtssperre

    Geltungsbereich

    Die Absichtssperre ist eine Tabellensperre

    Ich werde auf jeden Fall die Absichtssperre überprüfen.

    Das Absichtssperrprotokoll lautet wie folgt:

    Bevor eine Transaktion eine gemeinsame Sperre für eine Zeile in einer Tabelle erhalten kann, muss sie zunächst eine IS-Sperre oder eine stärkere Sperre erhalten auf dem Tisch.

    Bevor eine Transaktion eine exklusive Sperre für eine Zeile in der Tabelle erhalten kann, muss sie zunächst eine IX-Sperre für die Tabelle erhalten.

    Bevor Sie eine gemeinsame oder exklusive Sperre für eine Tabellensperre erwerben, muss die gemeinsame Sperre für die Tabelle überprüft werden.

    Die gegenseitigen Ausschlussregeln für Tabellensperren und Absichtssperren lauten wie folgt:

    X IX S IS

    X Konflikt Konflikt Konflikt Konflikt

    IX Konflikt kompatibel Konflikt kompatibel #🎜 🎜#S Konflikt Konfliktkompatibel Kompatibel

    IS Konfliktkompatibel Kompatibel Kompatibel



    Der Zweck der Absichtssperre ist: Wenn Sie eine Tabellensperre erwerben, können Sie die Absichtssperre schnell verwenden feststellen, ob es erworben werden kann.


    Denn beim Erwerb einer Sperre auf Zeilenebene wird zuerst die entsprechende Absichtssperre erworben, sodass andere Transaktionen beim Erwerb einer Tabellensperre die Absichtssperre schnell beurteilen können, ohne dass jede Zeile erforderlich ist . Gehen Sie scannen.

    Besonderer Hinweis ist, dass Absichtssperren überlagert werden können, d Erhalten Sie weiterhin die Absichtssperre IX2 und die Zeilenebenensperre X1, sodass die Absichtssperre nur vor dem Erwerb der Tabellenebenensperre überprüft wird.

    Datensatzsperre

    Die Datensatzsperre wirkt sich auf den Index aus, um die Datenzeile vor Änderungen durch andere Transaktionen zu schützen, wenn SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE.

    Die Datensatzsperre ist auch dann wirksam, wenn kein Index vorhanden ist, da innodb für jede Tabelle einen versteckten Index erstellt.

    Die Datensatzsperre ist die einfachste Zeilensperre.

    Lückensperre

    Die Lückensperre wirkt sich auf den Index aus und wird verwendet, um die Zeile nach dem Indexwert zu sperren, um das Einfügen zu verhindern. Sie wird wirksam, wenn aus der Tabelle ausgewählt wird, in der sich der Index befindet =? für update , zum Beispiel index=1, werden die Zeilen, die sich auf den Indexknoten mit index=1 beziehen, gesperrt, um zu verhindern, dass andere Transaktionen Daten einfügen .

    Aber die Update-Anweisung wird dadurch nicht verhindert, auch wenn die Update-Daten nicht vorhanden sind.

    Next-Key-Sperren

    Diese Sperre ist eine Kombination aus Datensatzsperre und Lückensperre, wenn bei der Auswahl aus der Tabelle index=? Es gibt Lückensperren, um Einfügungen zu verhindern, und Datensatzsperren für den Index, um das Aktualisieren und Löschen dieser Daten zu verhindern. Dieser Next-Key ist lediglich eine Verallgemeinerung dieser beiden Sperren, da diese beiden Sperren normalerweise zusammen angezeigt werden, wenn eine Aktualisierung ausgewählt wird.

    Intention Locks einfügen

    Intention Lock einfügen, der dem Intention Lock ähnelt. Es handelt sich um eine spezielle Lückensperre, die bei der Auswahl zur Aktualisierung nicht auftritt, jedoch beim gleichzeitigen Einfügen auftritt. Wenn beispielsweise zwei Transaktionen gleichzeitig den Indexbereich [4,7] einfügen, erhalten sie die Absicht Sperren Sie den Bereich gleichzeitig. Wenn die Transaktion blockiert ist, z. B. A: Einfügung-5, B: Einfügung-7, werden die beiden Transaktionen zu diesem Zeitpunkt nicht blockiert.

    Die Einfügungsabsichtssperre ist eine spezielle Lückensperre, die ein häufiges Blockieren des Einsatzes bei normalen Lückensperrintervallen verhindern soll, wie z. B. A: Einfügung-5, B: Einfügung-7, Wenn die Absichtssperre nicht eingefügt ist, versuchen sowohl 5 als auch 7, die Lückensperre zu erhalten. Zu diesem Zeitpunkt wird die zweite Transaktion blockiert. Durch das Einfügen der Absichtssperre wird jedoch nicht die zweite Transaktion blockiert, sondern nur die eingefügte Liegt tatsächlich ein Konflikt vor, wird dieser gesperrt.

    AUTO-INC-Sperren

    Auto-Inkrement-Sperre, diese Sperre ist offensichtlich eine Einfügungssperre auf Tabellenebene, um sicherzustellen, dass der Primärschlüssel der Tabelle mit einem Auto verknüpft ist -inkrementieren Primärschlüssel bleibt atomar inkrementiert.

    In Bezug auf Schlösser sollte jeder mehr über die Prinzipien und Modelle verschiedener Schlosskonstruktionen und -funktionen verstehen, damit er sie nach Vertiefung seines Verständnisses tiefer und gründlicher nutzen kann.

    Häufige Sperrennutzungsszenarien und Verwendung

    Doppelte Prüfung

    Wie wir alle wissen, sind MySQL-Transaktionen nutzlos, um wiederholte Einfügungen und eindeutige Indizes zu verhindern Es gibt viele Mängel, und es ist am besten, es im Geschäftsleben nicht zu verwenden. Daher besteht die übliche Methode zur Verhinderung wiederholter Einfügungen darin, verteilte Sperren zu verwenden.

    final WeekendNoticeReadCountDO weekendNoticeReadCountDO = weekendNoticeReadRepositoryService.selectByNoticeId(noticeRequestDTO.getNoticeId());
    if (weekendNoticeReadCountDO == null) {
        final String lockKey = RedisConstant.LOCK_WEEKEND_READ_COUNT_INSERT + ":" + noticeRequestDTO.getNoticeId();
        ClusterLock lock = clusterLockFactory.getClusterLockRedis(
            RedisConstant.REDIS_KEY_PREFIX,
            lockKey
        );
        if (lock.acquire(RedisConstant.REDIS_LOCK_DEFAULT_TIMEOUT)) {
            //double check
            final WeekendNoticeReadCountDO weekendNoticeReadCountDO = weekendNoticeReadRepositoryService.selectByNoticeId(noticeRequestDTO.getNoticeId());
            if (weekendNoticeReadCountDO == null) {
                try {
                    lock.execute(() -> {
                        WeekendNoticeReadCountDO readCountDO = new WeekendNoticeReadCountDO();
                        readCountDO.setNoticeId(noticeRequestDTO.getNoticeId());
                        readCountDO.setReadCount(1L);
                        readCountDO.setCreateTime(new Date());
                        readCountDO.setUpdateTime(new Date());
                        weekendNoticeReadRepositoryService.insert(readCountDO);
                        return true;
                    });
                } catch (ApiException err) {
                    throw err;
                } catch (Exception e) {
                    log.error("插入", e);
                    throw new ApiException(ErrorEnum.SERVER_ERROR.getCode(), "服务端出错");
                }
            } else {
                weekendNoticeReadRepositoryService.noticeCountAdd(weekendNoticeReadCountDO);
            }
        } else {
            log.warn("redis锁获取超时,key:{}", lockKey);
            throw new ApiException(ErrorEnum.SERVER_ERROR.getCode(), "服务器繁忙,请稍后重试");
        }
    }

    Nachdem die Sperre erworben wurde, kann sie nach dem Warten erworben werden. Zu diesem Zeitpunkt hat der vorherige Thread, der die Sperre freigegeben hat, möglicherweise Daten eingefügt, sodass diese innerhalb der Sperre noch erneut überprüft werden müssen. Prüfen Sie, ob die Daten vorhanden sind.
    Diese Schreibmethode eignet sich für die meisten Schreibszenarien, die Einzigartigkeit erfordern.

    Deadlock vermeiden

    Wie vermeide ich Deadlock? Die einfachste und effektivste Methode ist: **Lassen Sie das Schloss nicht in das Schloss gelangen. Kurz gesagt, es ist am besten, das Schloss allein zu verwenden, nicht als Nistpuppe.
    Achten Sie auch auf einige implizite Sperren, z. B. Datenbanken.
    Transaktion A:

    • [5,7] einfügen, Absichtssperre einfügen.

    • Auswählen für Update-Update [100,150], Lückensperre.
      Transaktion B:

    • Auswahl für Aktualisierung [90,120], Lückensperre.

    • Fügen Sie [4,6] ein und fügen Sie die Absichtssperre ein.

    Zu diesem Zeitpunkt kann es in einem gleichzeitigen Szenario vorkommen, dass A die Lückensperre von [5,7] hält und auf die Lückensperre von Transaktion B wartet [90,120] , das Gleiche gilt für Transaktion B, die blockiert ist.
    **

    Lassen Sie uns übrigens über häufige Probleme in Parallelitätsszenarien sprechen.

    Verwirrung beim Lesen und Schreiben Definieren einiger Tools Beim Hinzufügen oder Zwischenspeichern von Klassen kann es leicht passieren, dass man nachlässig ist und ähnliche Probleme verursacht.

    Beim Erstellen eines statischen Caches werden Methoden wie putIfAbsent in ConcurrentHashMap nicht verwendet und es wird keine Sperre zum Erstellen verwendet. Daher wird der Thread unten gelöscht, sobald der Thread oben ihn einfügt. oder der Cache wird doppelt erstellt.


    Redis oder einige gleichzeitige Vorgänge geben Sperren oder Ressourcen frei, ohne zu prüfen, ob der aktuelle Thread sie hält.

    Dies wird auch im Beispielcode der Redis-Sperre erwähnt.

    Thread A erhält die Sperre. Zu diesem Zeitpunkt ist die Ausführungszeit von A zu lang, sodass die Sperre aufgrund einer Zeitüberschreitung automatisch aufgehoben wird Nachdem A die Ausführung abgeschlossen hat, wurde beim Freigeben der Sperre nicht beurteilt, ob sie noch von ihm selbst gehalten wurde, was dazu führte, dass die von B gehaltene Sperre gelöscht wurde. Zu diesem Zeitpunkt erwarb C die Sperre erneut und BC wurde ausgeführt zur gleichen Zeit.

    Das obige ist der detaillierte Inhalt vonWelche Wissenspunkte gibt es im Zusammenhang mit Java- und MySQL-Sperren?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

    Stellungnahme:
    Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen