Heim >Datenbank >MySQL-Tutorial >Welche Wissenspunkte gibt es im Zusammenhang mit Java- und MySQL-Sperren?
In Computerprogrammen werden Sperren für exklusive Ressourcen verwendet. Erst wenn die Sperre erhalten wird, können die entsprechende Ressourcen betrieben werden.
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.
Es gibt 2 häufig verwendete Sperren in JVM
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:
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
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.
ReentrantLock
Die Implementierungslogik von AQS lautet wie folgt:
Geltungsbereich
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 KonfliktIX 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. 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. 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. 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 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-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. 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. 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. 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. [5,7] einfügen, Absichtssperre einfügen. Auswählen für Update-Update [100,150], Lückensperre. 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. Datensatzsperre
Lückensperre
Next-Key-Sperren
Intention Locks einfügen
AUTO-INC-Sperren
Häufige Sperrennutzungsszenarien und Verwendung
Doppelte Prüfung
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(), "服务器繁忙,请稍后重试");
}
}
Diese Schreibmethode eignet sich für die meisten Schreibszenarien, die Einzigartigkeit erfordern. Deadlock vermeiden
Achten Sie auch auf einige implizite Sperren, z. B. Datenbanken.
Transaktion A:
Transaktion B:
**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!