Wie lange lässt sich MSMQ noch nutzen? ── Die Migrationsentscheidung für eine Legacy-Queue, die nicht einmal „deprecated“ ist
· Go Komura · Windows, .NET, C#, MSMQ, Nachrichtenwarteschlange, Legacy-Technologie, Migration, Informationssysteme
„Dieses System verwendet MSMQ, und ich habe gehört, das sei eingestellt worden. Müssen wir jetzt sofort migrieren?“ ── diese Frage höre ich seit etwa einem Jahr immer wieder in Beratungsgesprächen zu Legacy-Migrationen.
Die Antwort ist etwas verdreht. MSMQ (Microsoft Message Queuing) ist alles andere als eingestellt — es ist nicht einmal offiziell deprecated. Stand Juli 2026 steht der Name MSMQ auf keiner offiziellen Deprecated-Liste von Microsoft, und es wird auch in aktuellen Windows-Versionen als optionales Feature mitgeliefert. Dass es sich im Feld trotzdem wie eine „erledigte Technologie“ anfühlt, liegt daran, dass die offizielle Managed API auf der .NET-Seite geschlossen ist. System.Messaging, die Standardbibliothek für den Umgang mit MSMQ, existiert nur im .NET Framework und wurde nie auf .NET (Core und neuer) portiert.
Mit anderen Worten: MSMQ ist keine Technologie, die „morgen aufhört zu funktionieren“, sondern eine Technologie, die in dem Moment zur Wand wird, in dem Sie versuchen, Ihre Anwendung auf .NET zu heben.
Dieser Artikel richtet sich an Entwickler, die für Wartung und Migration bestehender MSMQ-Systeme zuständig sind, sowie an Mitarbeiter der IT-Abteilung, die diese Entscheidung treffen müssen. Das Ziel ist, das Gerücht „angeblich eingestellt“ auf seinen Wahrheitsgehalt zu prüfen und in die Lage zu kommen, anhand der Bedingungen in Ihrer eigenen Umgebung selbst zu entscheiden, ob migriert werden soll.
Dieser Artikel trennt zunächst Gerücht von Tatsache und ordnet dann die Entscheidung zwischen Weiternutzung und Migration sowie die Wahl des Migrationsziels. Die Migration von VB6 oder .NET Framework selbst wird in „Praxisleitfaden für die Migration von VB6 zu .NET“ und „Checkliste vor der Migration von .NET Framework zu .NET“ behandelt, weshalb sich dieser Artikel auf den Teil rund um die Queue beschränkt.
1. Das Wichtigste zuerst
- MSMQ ist offiziell nicht deprecated. Es taucht weder in der Deprecated-Liste des Windows-Clients noch in der Windows-Server-Liste der entfernten bzw. nicht mehr weiterentwickelten Features auf (Stand Juli 2026).12
- Es gibt jedoch keine offizielle Managed API für .NET. System.Messaging deckt nur .NET Framework 1.1 bis 4.8.1 ab,3 und es ist auch nicht im Windows Compatibility Pack enthalten, dem Standardweg für die Migration zu .NET.4 Der Weg über die native Win32-API per P/Invoke bleibt offen, sollte aber als Übergangslösung betrachtet werden (Abschnitt 3).
- Es gibt eine Portierung über CoreWCF, aber sie deckt nur die Migration eines über die Queue aufgerufenen WCF-Dienstes (der Empfängerseite) ab und ist ein Weg, den man nur nach Prüfung der Bedingungen einschlagen sollte. CoreWCF selbst besitzt eine Support-Richtlinie von Microsoft, doch die Implementierung des MSMQ-Transports (CoreWCF.MSMQ) hängt von einer Community-Portierung des System.Messaging der .NET-Framework-Version ab.5
- Die Achse der Entscheidung ist, ob Sie die Anwendung auf .NET heben. Wenn ja, gilt als Grundsatz, die Queue gleich mit zu migrieren (eine Lebensverlängerung per P/Invoke oder CoreWCF ist ebenfalls möglich, bedeutet aber, die Wartungslast bewusst zu übernehmen). Wenn nicht (Belassen im Ist-Zustand), lässt sich planen, das System so lange weiterlaufen zu lassen, wie .NET Framework 4.8 als Betriebssystemkomponente unterstützt wird.6
- Erster Kandidat für das Migrationsziel ist nicht ein Message-Broker, sondern eine Tabellen-Queue in der Datenbank. Die Konsistenz, die MSMQ zusammen mit einer verteilten Transaktion (DTC) sichergestellt hat, lässt sich durch eine Tabellen-Queue, die in derselben Transaktion wie die Fachdaten verarbeitet wird, unkomplizierter ersetzen (Abschnitt 5).
- Machen Sie zuerst eine Bestandsaufnahme der Nachrichtenformate. Die BinaryFormatter-basierte Serialisierung wurde in .NET 9 aus der Laufzeit entfernt,7 und wenn Sie altes und neues Format nebeneinander bestehen lassen, geraten Sie ins Stocken (Abschnitt 6).
2. MSMQ in 30 Sekunden
MSMQ ist die Message-Queuing-Plattform, die seit jeher mit Windows ausgeliefert wird. Eine Anwendung schreibt eine Nachricht in eine Queue, und eine andere Anwendung (auf derselben Maschine oder auf einer anderen) entnimmt sie, wann es ihr passt. Die charakteristischen Eigenschaften lassen sich auf drei Punkte verdichten.
- Store-and-Forward: Auch wenn das Ziel nicht erreichbar ist, wird die Nachricht lokal gespeichert und zugestellt, sobald das Ziel wieder verfügbar ist. Das macht die Lösung robust gegenüber instabilen Verbindungen zwischen Standorten. Diese Persistenz gilt allerdings nicht bedingungslos: Die standardmäßigen schnellen (Express-)Nachrichten können ausschließlich im Speicher verbleiben und gehen bei einem Neustart des MSMQ-Diensts oder der Maschine verloren. Auf die Festplatte geschrieben werden nur Nachrichten, bei denen der Sender Recoverable (wiederherstellbar) angegeben hat, sowie transaktionale Nachrichten.
- Transaktionen: Queue-Operationen lassen sich als Transaktion ausführen, und in Kombination mit MS DTC (dem Distributed Transaction Coordinator) lassen sich „das Entnehmen aus der Queue“ und „die Datenbankaktualisierung“ als eine einzige verteilte Transaktion festschreiben.
- Im Betriebssystem enthalten: Weil es sich ohne die Installation zusätzlicher Middleware nutzen ließ, fand es in den Fachanwendungen der 2000er-Jahre breite Verwendung — insbesondere bei der Anbindung von Auftragsdaten, der asynchronen Verarbeitung von Berichten und der Verknüpfung von Arbeitsschritten in der Fertigung.
Gerade weil diese Kombination — im Betriebssystem enthalten, transaktionsfähig, robust im Offline-Betrieb — so überzeugend war, ist MSMQ bis heute im aktiven Einsatz. Auch beim Nachdenken über ein Migrationsziel steht im Zentrum der Entscheidung, welche dieser drei Eigenschaften tatsächlich genutzt wird.
Das Mindestset an Begriffen für diesen Artikel
Die Entscheidungstabelle in Abschnitt 5 und die Bestandsaufnahme in Abschnitt 6 setzen die folgenden Begriffe voraus. Klären Sie sie hier auf einen Schlag.8
- Private Queue ── eine Queue, die nicht in einem Verzeichnisdienst (Active Directory) veröffentlicht, sondern nur auf diesem einen Computer registriert wird. Sie wird in einer Form wie
.\private$\Queuenameangegeben. Ihr Gegenstück, die öffentliche Queue, wird im Verzeichnisdienst registriert und lässt sich innerhalb der Domäne suchen. In kleinen und mittleren Fachanwendungen handelt es sich fast immer um private Queues. - Express-Nachricht ── der Standard-Sendemodus. Schnell, weil die Nachricht sowohl während als auch nach der Zustellung im Speicher liegt, geht aber verloren, wenn der MSMQ-Dienst oder die Maschine stoppt.
- Recoverable (wiederherstellbare) Nachricht ── ein Modus, bei dem die Nachricht beim Sender und auf jedem vermittelnden Computer auf die Festplatte geschrieben und auch in der Zielqueue auf der Festplatte gehalten wird. Sie übersteht einen Neustart. Der Sender muss dies ausdrücklich angeben.
- Transaktions-Queue ── eine Queue, die ausschließlich transaktionale Nachrichten verarbeitet. Das wird bei der Erstellung der Queue festgelegt und lässt sich später nicht mehr ändern (das wirkt sich auf das Migrationsverfahren in Abschnitt 6 aus).
- DTC (Distributed Transaction Coordinator) ── ein Windows-Dienst, der Transaktionen koordiniert, die sich über mehrere Ressourcen erstrecken (etwa eine MSMQ-Queue und eine Datenbank). Der Mechanismus, der „das Entnehmen aus der Queue“ und „die DB-Aktualisierung“ gemeinsam festschreibt, und der größte Streitpunkt bei der Migrationsentscheidung in Abschnitt 5.
- Journal-Queue / Queue für unzustellbare Nachrichten (Dead Letter) ── von MSMQ automatisch erzeugte Systemqueues. Das Journal sammelt „Kopien gesendeter/entnommener Nachrichten“, die Dead-Letter-Queue sammelt „nicht zustellbare Nachrichten“. Bleiben sie unbeaufsichtigt, fressen sie Speicherplatz und müssen deshalb beim Belassen im Ist-Zustand überwacht werden (Abschnitt 7).
3. Die Faktenlage ── „eingestellt“ ist nicht zutreffend
Die Frage „Lässt sich MSMQ noch nutzen?“ führt zu Verwirrung, weil die Antwort je nach Ebene unterschiedlich ausfällt, aber trotzdem so behandelt wird, als gäbe es nur eine einzige Antwort. Zunächst das Gesamtbild in einer Tabelle.
| Ebene | Aktueller Stand | Praktische Bedeutung |
|---|---|---|
| Betriebssystemfunktion (optionales Windows-Feature) | Besteht fort. Wird mit aktuellen Windows-Client-/Server-Versionen ausgeliefert, keine Deprecation-Ankündigung12 | Nach Aktivierung funktioniert es weiterhin. Lässt sich innerhalb des Support-Zeitraums des Betriebssystems weiter nutzen |
Win32-native API (MQSendMessage u. a.) |
Dokumentiert und nutzbar9 | Der Weg, sie per P/Invoke aus .NET aufzurufen, bleibt offen. Formatter und Transaktionsanbindung müssen aber selbst geschrieben und gepflegt werden |
| System.Messaging im .NET Framework | Nutzbar. Deckt aber nur .NET Framework 1.1 bis 4.8.1 ab3 | Bestehende Systeme laufen hierauf. Danach kommt nichts mehr |
| Offizielle Managed API für .NET (Core und neuer) | Existiert nicht. Auch nicht im Windows Compatibility Pack enthalten4 | In dem Moment, in dem die Anwendung auf .NET gehoben wird, muss der Queue-Teil neu gebaut werden |
| MSMQ-Binding von WCF → CoreWCF.MSMQ | Eine community-geführte Portierung existiert. CoreWCF selbst hat eine Support-Richtlinie, aber die MSMQ-Implementierung hängt von einer Community-Portierung von System.Messaging ab5 | Nutzbar, um einen über die Queue aufgerufenen WCF-Dienst (die Empfängerseite) am Leben zu halten, aber weder Ersatz für die Senderseite noch eine allgemeine Queue-API |
| Neueinsatz | Nicht empfehlenswert | Weil es keinen offiziellen Weg in die Zukunft gibt |
Im Folgenden prüfen wir der Reihe nach die Grundlage für jede Zeile dieser Tabelle.
Erstens: MSMQ steht nicht auf der Deprecated-Liste. Wirft man einen Blick in die „Deprecated features“-Liste des Windows-Clients, finden sich dort NTLM, VBScript und WordPad, aber kein Eintrag für MSMQ.1 Auch in der Liste „Features Removed or No Longer Developed“ von Windows Server, einschließlich der Registerkarte für Windows Server 2025, wird MSMQ nicht genannt.2 Deprecated ist eine offizielle Erklärung, dass „die aktive Entwicklung eingestellt wurde“ — und der aktuelle Stand ist, dass nicht einmal diese Erklärung abgegeben wurde.
Zweitens: System.Messaging bleibt beim .NET Framework stehen. Die von der Referenzdokumentation abgedeckten Versionen reichen von .NET Framework 1.1 bis 4.8.1, eine Version für .NET (Core und neuer) existiert nicht.3 Das Windows Compatibility Pack (Microsoft.Windows.Compatibility), der Auffangbehälter für .NET-Framework-exklusive APIs, stellt rund 20.000 APIs bereit — für Registry, WMI, Windows-Dienste, EventLog und mehr —, aber seine Liste der Technologiebereiche enthält kein Messaging (System.Messaging).4 Genau genommen ist es die Managed API, die geschlossen ist. MSMQs native Win32-API (MQSendMessage, MQReceiveMessage und andere) ist nach wie vor dokumentiert, und sie aus .NET per P/Invoke aufzurufen, ist an sich möglich. Allerdings müssen Sie Formatter und Transaktionsanbindung, die System.Messaging bislang übernommen hat, als eigenen Wrapper schreiben und dauerhaft pflegen — daher ist das nicht „die eigentliche Lösung zur Weiternutzung“, sondern eine „Übergangslösung für den Fall, dass man unbedingt daran festhalten muss“.
Drittens: Auch die MSMQ-Anbindung von WCF sitzt hinter derselben Wand. WCF im .NET Framework besaß ein Binding, das MSMQ als Unterbau nutzte, aber versucht man, diesen Pfad in modernem .NET nachzubilden, landet man beim community-geführten CoreWCF. CoreWCF veröffentlicht als Teil seiner queue-basierten Transporte ein MSMQ-Paket (CoreWCF.MSMQ), doch dessen Implementierung nennt ausdrücklich eine Abhängigkeit von einer Community-Portierung der .NET-Framework-Version der System.Messaging-Bibliothek.5 Ob es funktioniert: Ja, es funktioniert, und CoreWCF selbst besitzt eine offizielle Support-Richtlinie von Microsoft, sodass es sich auch nicht um „eine völlig wildwüchsige Bibliothek“ handelt.5 Ob dieselbe Behandlung aber bis zur Community-Portierung von System.Messaging reicht, von der der MSMQ-Transport abhängt, ist eine andere Frage. Wenn Sie es einsetzen, entscheiden Sie erst, nachdem Sie geprüft haben, ob die verwendete Version unter die Support-Richtlinie fällt und wie mit diesem abhängigen Teil umgegangen wird.
Das ist die Grundlage für jede Zeile der Tabelle vom Anfang dieses Abschnitts. Es ist nicht so, dass „MSMQ eingestellt wurde“ — sondern dass „es keinen offiziellen Weg von modernem .NET zu MSMQ gibt“. Wenn Sie diese Unterscheidung im Kopf behalten, führen interne Diskussionen leichter zueinander.
4. Was hinter „es läuft, aber es ist ein Problem“ steckt
Beratungen zu Systemen mit MSMQ beginnen meist nicht mit einer Störung, sondern mit einer Migrationsschätzung. Das eigentliche Problem ist nicht MSMQ selbst, sondern dass MSMQ zu einem Anker wird, der die gesamte Anwendung an das .NET Framework fesselt.
.NET Framework 4.8 wird als Windows-Komponente behandelt und entlang des Lebenszyklus des installierten Betriebssystems unterstützt.6 Die Frage „Läuft es weiter?“ lässt sich deshalb mit „vorerst läuft es weiter“ beantworten. Trotzdem werden die folgenden Punkte mit der Zeit garantiert schwerer.
- Man findet kein Personal, und man kann nicht übergeben. Die Zahl der Techniker, die System.Messaging und DTC erklären können, sinkt Jahr für Jahr. Ein typisches Beispiel für das Muster, das in „Wenn Sie ein System ohne Quellcode und ohne Dokumentation übernehmen“ beschrieben wird.
- Man profitiert nicht von der Laufzeitumgebung oder neuen Bibliotheken. Viele neuere C#-Sprachfunktionen lassen sich allein durch ein Compiler-Update auch im .NET Framework nutzen, aber Performance-Verbesserungen auf Laufzeitseite und neuere Standardbibliotheken bleiben verwehrt, und zunehmend fallen auch neuere Pakete weg, die die Unterstützung für .NET Framework einstellen.
- Die verteilte Transaktion wird zum schwierigsten Teil der Migration. Das Design von MSMQ+DTC — „Queue-Entnahme und DB-Aktualisierung atomar“ — lässt sich mit cloudbasierten Queue-Diensten nicht nachbilden. Lässt man das liegen und modernisiert nur das Umfeld auf .NET, bleibt zum Schluss der härteste Kern übrig.
- Eine Zeitbombe im Serialisierungsformat. Der Nachrichtentext älterer Systeme ist mitunter binär serialisiert, und BinaryFormatter wurde in .NET 9 aus der Laufzeit entfernt.7 Bei der Migration muss das Nachrichtenformat selbst überprüft werden.
Die praktische Antwort auf die Frage „Wie lange lässt sich MSMQ noch nutzen“ lautet also: „Es läuft, solange das Betriebssystem es unterstützt, aber der Schwierigkeitsgrad der Migration steigt garantiert mit jedem Tag, den man wartet.“ Selbst wenn Sie die Entscheidung aufschieben, sollten Sie zumindest mit der Entscheidungstabelle im nächsten Abschnitt vorab klären, „wo die Schwierigkeiten liegen“.
5. Entscheidungstabelle für das Migrationsziel
Das Migrationsziel wählt man nicht danach, „welches Produkt MSMQ beerbt“, sondern nach der jeweils tatsächlich genutzten Eigenschaft.
5.1. Zunächst die Anforderung auf vier Fragen herunterbrechen
- Ist die Gegenstelle der Queue (der empfangsseitige Prozess) ein Prozess, der die eigene Datenbank aktualisiert?
- Wird eine verteilte Transaktion (DTC) verwendet? (Transaktions-Queue + DB-Aktualisierung)
- Befinden sich Sender und Empfänger auf unterschiedlichen Maschinen bzw. an unterschiedlichen Standorten? Wird die Offline-Robustheit (Store-and-Forward) tatsächlich genutzt?
- Wie hoch ist das Nachrichtenaufkommen tatsächlich? (Bei den meisten Fachanwendungen liegt es bei einigen Tausend bis einigen Zehntausend pro Tag — das bewältigt jede der hier genannten Optionen mühelos.)
5.2. Die Entscheidungstabelle
| Genutzte Eigenschaft | Erster Kandidat | Begründung und Hinweise |
|---|---|---|
| Asynchrone Verarbeitung innerhalb desselben Systems (Empfängerseite aktualisiert die DB) | Tabellen-Queue in der DB | „Nachricht entnehmen“ und „Fachdaten aktualisieren“ lassen sich in derselben lokalen Transaktion festschreiben, wodurch DTC überflüssig wird. Vorhandene Backup-, Monitoring- und Betriebsprozesse lassen sich unverändert weiterverwenden. Auch auf der Senderseite lassen sich „Fachdaten aktualisieren und Nachrichtenzeile einfügen“ in dieselbe Transaktion legen — das ist das sogenannte Outbox-Muster |
| Queue und DB-Aktualisierung werden per DTC atomar gemacht | Tabellen-Queue in der DB | Das Wesen der Migration besteht darin, die verteilte Transaktion durch eine lokale Transaktion zu ersetzen. Cloud-Queue-Dienste können nicht an DTC teilnehmen — solange diese Anforderung besteht, ist ein Broker-Ansatz ein Umweg |
| Lose gekoppelte Anbindung zwischen mehreren Systemen/Sprachen | RabbitMQ (On-Premises) / Azure Service Bus (cloudfähig) | Fan-out und Routing der Zustellung sind die Stärke eines Brokers. Bei RabbitMQ sollten Sie den Aufwand des Eigenbetriebs (Redundanz, Updates) einkalkulieren |
| Offline-Robustheit zwischen Standorten (Store-and-Forward) | Azure Service Bus u. Ä. + Wiederholungsdesign, oder standortseitige Tabellen-Queue + Synchronisierung | Es gibt kaum Mechanismen, die MSMQs „lokal beim Sender sammeln und später zustellen“ transparent ersetzen. Ändern Sie das Design so, dass die Anwendung selbst ausdrücklich die Verantwortung für das Sammeln beim Sender übernimmt |
| Produzent/Konsument innerhalb desselben Prozesses | In-Memory-Queue wie .NETs Channels | Ein Fall, in dem eigentlich nie eine prozessübergreifende Queue nötig war. Im Prozess belassen, bei Bedarf an Persistenz zur Tabellen-Queue wechseln |
| Nur als Interprozesskommunikation zwischen Windows-Diensten genutzt | IPC wie Named Pipes | Ersetzbar aber nur, wenn beide Seiten stets gleichzeitig laufen. Auch während die Empfängerseite steht, nimmt MSMQ (selbst bei Express-Nachrichten) Sendungen an und liefert sie später aus, eine Pipe schlägt dagegen sofort fehl. Wenn Sie sich auf die Ansammlung während eines Stillstands verlassen, implementieren Sie Wiederholung/Pufferung in der Anwendung selbst, oder behalten Sie die Queue. Zur Auswahl siehe „Windows-Prozesskommunikation richtig wählen“ |
5.3. Eine minimale Implementierung der Tabellen-Queue
Viele können mit dem Begriff „Tabellen-Queue“ zunächst wenig anfangen, deshalb zeigen wir die minimale Form. Zunächst die Tabellendefinition (SQL Server).
CREATE TABLE dbo.JobQueue (
Id BIGINT IDENTITY(1,1) PRIMARY KEY,
Payload NVARCHAR(MAX) NOT NULL, -- Inhalt. Wird als JSON gehalten
Status TINYINT NOT NULL DEFAULT 0, -- 0: unverarbeitet 1: in Bearbeitung 2: abgeschlossen
EnqueuedAt DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME(),
StartedAt DATETIME2 NULL, -- Wird verwendet, um Zeilen zurückzuholen, die während der Bearbeitung abgestürzt sind
RetryCount INT NOT NULL DEFAULT 0
);
CREATE INDEX IX_JobQueue_Status ON dbo.JobQueue (Status, Id);
Beim Entnehmen wird genau eine Zeile als „in Bearbeitung“ markiert, während der Inhalt gelesen wird. Mit READPAST lassen sich Zeilen, die von anderen Workern gesperrt sind, überspringen, ohne zu warten (mehrere Prozesse können so parallel laufen).
WITH next_job AS (
SELECT TOP (1) *
-- READCOMMITTEDLOCK ist auf einer DB nötig, bei der READ_COMMITTED_SNAPSHOT auf ON steht (siehe unten).
-- Bei OFF entspricht das dem Standardverhalten, es kann also stehen bleiben und wirkt für beide Fälle
FROM dbo.JobQueue WITH (READPAST, UPDLOCK, READCOMMITTEDLOCK)
WHERE Status = 0
ORDER BY Id -- In Einfügereihenfolge entnehmen. Das ist die Bedingung dafür, überhaupt eine "Queue" zu sein
)
UPDATE next_job
SET Status = 1, StartedAt = SYSUTCDATETIME()
OUTPUT inserted.Id, inserted.Payload;
READPAST lässt sich auf einer Datenbank, bei der READ_COMMITTED_SNAPSHOT auf ON steht, nicht unverändert nutzen. Die offizielle Dokumentation hält ausdrücklich fest: „Wenn READ_COMMITTED_SNAPSHOT auf ON steht und die Isolationsstufe der Sitzung READ COMMITTED ist (oder zusätzlich der Hinweis READCOMMITTED verwendet wird), kann READPAST nicht angegeben werden“, und nennt als Abhilfe in diesem Fall, den Hinweis READCOMMITTEDLOCK zusätzlich anzugeben.10 Da die Standard-Isolationsstufe READ COMMITTED ist, führt diese Entnahme auf einer Datenbank, bei der lediglich READ_COMMITTED_SNAPSHOT aktiviert wurde, nicht nur dazu, dass „Zeilen anderer Worker nicht übersprungen werden“ — die Anweisung selbst schlägt mit einem Fehler fehl. Bei Azure SQL Database steht das standardmäßig auf ON, und auch On-Premises ist es keine Seltenheit, dies als Gegenmaßnahme gegen Lese-Blockierungen zu aktivieren. Prüfen Sie vorab, wie es sich bei Ihrer Ziel-Datenbank verhält.
SELECT is_read_committed_snapshot_on FROM sys.databases WHERE name = DB_NAME();
Dass ROWLOCK aus dem häufig gesehenen WITH (READPAST, UPDLOCK, ROWLOCK) weggelassen wurde, liegt daran, dass ROWLOCK und READCOMMITTEDLOCK zur selben Gruppe von „Granularitätshinweisen“ gehören und sich nicht beide auf einer Tabelle angeben lassen.10 READPAST kann nur Zeilensperren überspringen, keine Seitensperren, weshalb man ROWLOCK gerne explizit angeben würde — bei der einen Zeile, die ein TOP (1)-Indexsuchlauf holt, kommt es praktisch nie zu einer Eskalation. Wenn Sie sicher wissen, dass READ_COMMITTED_SNAPSHOT auf OFF steht, und ROWLOCK explizit angeben möchten, lassen Sie stattdessen READCOMMITTEDLOCK weg.
Lässt man ORDER BY weg und schreibt UPDATE TOP (1), wird unbestimmt, welche Zeile ausgewählt wird. Offiziell ist festgehalten, dass TOP bei UPDATE die betroffenen Zeilen nicht sortiert, sodass auch ein Index auf (Status, Id) keine Garantie für die Entnahmereihenfolge ist.11 Bei einer Anbindung, die voraussetzt, dass in Einfügereihenfolge verarbeitet wird, äußert sich das als Fehler, bei dem ältere Jobs dauerhaft nach hinten geschoben werden.
ORDER BY Id sorgt allerdings nur für die Reihenfolge, in der Zeilen entnommen werden. Die Reihenfolge, in der die Verarbeitung abgeschlossen wird, ist damit nicht garantiert. READPAST dient ja gerade dazu, „von anderen Workern gesperrte Zeilen zu überspringen“, sodass Worker B Job 2 ergreifen und zuerst committen kann, während Worker A Job 1 hält und lange braucht.
| Was garantiert ist | Was nicht garantiert ist |
|---|---|
Welche Zeile zuerst entnommen wird (ORDER BY Id) |
Welche Zeile zuerst in den Fachdaten wirksam wird |
Bei Anbindungen, bei denen die Reihenfolge der Wirksamkeit eine Rolle spielt — etwa „es ist ein Problem, wenn sich Aktualisierungen zur selben Bestellnummer vertauschen“ —, reicht das nicht aus. Es gibt zwei mögliche Formen.
- Einen einzigen Konsumenten verwenden. Parallelität aufgeben, um Reihenfolge zu erhalten. Reicht der Durchsatz aus, ist das die einfachste und robusteste Form.
- Nach Schlüssel aufteilen. Entweder Worker an einen Schlüssel wie die Bestellnummer binden, oder auf der Entnahmeseite die Bedingung „nicht entnehmen, wenn eine Zeile mit demselben Schlüssel bereits in Bearbeitung ist“ hinzufügen, sodass die Reihenfolge nur innerhalb eines Schlüssels garantiert wird. Auf eine Reihenfolge über Schlüssel hinweg wird verzichtet.
Wenn Sie sich für keine der beiden Varianten entscheiden, halten Sie im Migrationsdesign ausdrücklich fest, dass es in dem Moment, in dem parallel gearbeitet wird, keine globale FIFO-Garantie mehr gibt. Das wird gerade bei einer Migration von MSMQ besonders leicht übersehen. Dasselbe passiert auch bei MSMQ-Queues, sobald parallel empfangen wird, aber wenn man mit der Annahme „es ist eine Queue, also läuft es der Reihe nach ab“ hinüberwechselt, sieht es so aus, als wäre das Reihenfolgeproblem erst mit der Umstellung auf die Tabellen-Queue aufgetaucht.
Der empfangsseitige Worker führt das einfach innerhalb derselben lokalen Transaktion wie die Fachverarbeitung aus (C#, Pseudocode).
while (!stoppingToken.IsCancellationRequested)
{
using var tx = connection.BeginTransaction();
var job = DequeueOne(connection, tx); // Das UPDATE ... OUTPUT von oben
if (job is null)
{
tx.Commit();
await Task.Delay(TimeSpan.FromSeconds(1), stoppingToken); // Bei leerer Queue nur das Polling-Intervall abwarten
continue;
}
ApplyBusinessData(connection, tx, job); // <- Aktualisierung der Fachdaten (die eigentlich gewünschte Arbeit)
MarkDone(connection, tx, job.Id); // Status = 2
tx.Commit(); // "Entnahme" und "Fachaktualisierung" werden mit dieser einen Zeile gemeinsam festgeschrieben
}
Das ist der Punkt, an dem MSMQ+DTC ersetzt wird. Bei MSMQ waren „Entnahme aus der Queue“ und „DB-Aktualisierung“ getrennte Ressourcen, weshalb eine verteilte Transaktion (DTC) nötig war, um beide zusammenzufassen. Ist die Queue eine DB-Tabelle, sind beides Aktualisierungen derselben Datenbank, sodass eine gewöhnliche lokale Transaktion genügt. Führt man RabbitMQ oder Azure Service Bus ein, geht diese Eigenschaft verloren (Queue und DB werden wieder zu getrennten Ressourcen), und Idempotenz sowie Wiederholung müssen in der Anwendung selbst eingebaut werden.
Im laufenden Betrieb müssen ungefähr diese drei Dinge noch ergänzt werden.
- Zurückholen von Zeilen, die während der Bearbeitung abgestürzt sind. Nehmen Sie einen periodisch laufenden Wiederherstellungsprozess auf, der Zeilen mit
Status = 1, derenStartedAtälter als eine bestimmte Zeitspanne ist, aufStatus = 0zurücksetzt. - Obergrenze für Wiederholungen und Abstellgleis. Zeilen, bei denen
RetryCountdie Obergrenze überschreitet, werden in eine separate Tabelle (oderStatus = 9) verschoben. Das entspricht dem Ablageort der Dead-Letter-Queue von MSMQ. - Aufräumen abgeschlossener Zeilen. Löschen oder archivieren Sie Zeilen mit
Status = 2regelmäßig. Lässt man sie liegen, wächst die Tabelle, und die Wirksamkeit der Indizes nimmt ab.
Auf der Senderseite legen Sie die Aktualisierung der Fachdaten und das INSERT der Nachrichtenzeile in dieselbe Transaktion (das Outbox-Muster). Damit verschwindet auch die Inkonsistenz, dass „die Fachdaten aktualisiert wurden, aber keine Nachricht hinausgegangen ist“.
Betonen möchte ich, dass bei kleinen und mittleren Fachanwendungen die Tabellen-Queue häufig der erste Kandidat ist. Vergleichsartikel zu Message-Queue-Produkten neigen zur Form „RabbitMQ vs. Kafka vs. Service Bus“, aber was Systeme der MSMQ-Generation meist auf eine Queue legen, ist „ein asynchroner Job, der dieselbe DB aktualisiert“ — und das lässt sich mit einer DB-Tabelle und Polling (oder Benachrichtigung) ausreichend und dazu einfacher realisieren. Die Betriebskosten einer zusätzlichen Middleware (Monitoring, Redundanz, Patches, Schulung des Personals) wiegen bei kleinen und mittleren Teams besonders schwer.
6. Das praktische Migrationsverfahren
Das Vorgehen folgt dem Standardrezept für Legacy-Migrationen: „erst beobachten, dann handeln“.
-
Bestandsaufnahme der Abhängigkeiten. Durchsuchen Sie den Code nach Referenzen auf
System.Messagingund nach Stellen, an denenMessageQueueerzeugt wird. Suchen Sie zusätzlich in den WCF-Konfigurationsdateien nachnetMsmqBinding/msmqIntegrationBindingsowie nach Aufrufen der nativen API (MQ*-Funktionen wieMQSendMessage) oder über COM. Auch ohne Referenz auf System.Messaging kann ein Pfad von MSMQ abhängen. Zu prüfende Punkte sind: (a) der Pfad der Queue (lokal oder remote, privat oder öffentlich), (b) ob es eine Transaktions-Queue ist und ob Nachrichten als Recoverable markiert werden (ist beides nicht der Fall, läuft das bestehende System unter der Annahme, dass Nachrichten bei einem Neustart verloren gehen), (c) der Formatter (XmlMessageFormatter/BinaryMessageFormatter/ActiveXMessageFormatter), (d) die Nutzung von Journal- und Dead-Letter-Queue, sowie (e) wer die Queue erstellt und löscht (Installer oder Anwendung).Die Bestandsaufnahme allein wirkt sich noch nicht auf die Migrationsentscheidung aus. Füllen Sie in der folgenden Form eine Zeile pro Queue aus und nutzen Sie das direkt als Grundlage für die Migrationsstrategie (das lässt sich unverändert als Anlage zu einem Genehmigungsdokument beifügen).
Punkt Wo nachsehen Was aufzeichnen Wie es die Entscheidung beeinflusst (a) Pfad der Queue Der an MessageQueueübergebene Pfad-String, das Ziel in der Konfigurationsdatei, die AngabeFormatName:Lokal/Remote, privat/öffentlich, Name der Gegenstelle Bei Remote/standortübergreifend Bedarf an Store-and-Forward beurteilen (Zeile „Offline-Robustheit“ in 5.2). Bei rein lokal fällt es in die erste Zeile von 5.2 (b) Transaktion und Recoverable Erstellungsstelle der Queue (Transaktions-Queue?), ob beim Senden Recoverable angegeben wird, ob DTC verwendet wird Ob es eine Transaktions-Queue ist, ob Recoverable angegeben wird, ob DTC beteiligt ist Bei DTC ist eine Tabellen-Queue als Migrationsziel praktisch gesetzt. Trifft beides nicht zu, dokumentieren Sie ausdrücklich, dass der aktuelle Betrieb unter der Annahme läuft, dass „Nachrichten bei einem Neustart verschwinden“ (c) Formatter Fundstellen von XmlMessageFormatter/BinaryMessageFormatter/ActiveXMessageFormatterVerwendeter Formatter und Typ des Nachrichtentexts Bei BinaryFormatter-Familie ist die Umstellung auf JSON zwingend (Schritt 2). Ein Hauptfaktor für den Migrationsaufwand7 (d) Journal- / Dead-Letter-Queue Eigenschaften der Queue (Journal aktiviert?), Inhalt der Systemqueues, Betriebshandbücher Ob das Journal genutzt wird, ob die Dead-Letter-Queue tatsächlich eingesehen wird „Wie fehlgeschlagene Nachrichten behandelt werden“ wird zur Designanforderung des Migrationsziels (bei einer Tabellen-Queue eine Abstelltabelle) (e) Wer erstellt/löscht Installer, Deployment-Skripte, Create-Aufrufe beim AnwendungsstartWer erstellt und wer die Berechtigungen konfiguriert Bei der Migration überträgt sich direkt, „wer die neue Queue bereitstellt“. Wählen Sie das Belassen im Ist-Zustand, übertragen Sie das ins Kitting-Verfahren (Abschnitt 7) - Das Nachrichtenformat festlegen. Machen Sie JSON zum Standardformat nach der Migration. Was Sie nicht mitbringen dürfen, ist eine BinaryFormatter-basierte Serialisierung wie
BinaryMessageFormatter. BinaryFormatter wurde in .NET 9 entfernt und wird auch aus Sicherheitsgründen nicht empfohlen.7 Verwenden Sie hingegen ein binäres Format, dessen Spezifikation unabhängig gepflegt wird, wie Protocol Buffers oder MessagePack, ist es unproblematisch, dieses Format unverändert in das neue System zu übernehmen. - Zuerst die Empfängerseite migrieren. Stellen Sie zuerst die neue Queue (etwa eine Tabellen-Queue) bereit, machen Sie die Verarbeitung auf der Empfängerseite für die neue Queue tauglich, und schalten Sie erst dann die Senderseite um. Während der Migrationsphase erspart Ihnen eine kleine Brücke, die Nachrichten von der alten MSMQ-Queue in die neue überführt (die durchaus im .NET Framework bleiben kann), es, alle Sender auf einen Schlag umzustellen. Stürzt diese Brücke jedoch zwischen „Entnahme aus MSMQ“ und „Schreiben in die neue Queue“ ab, geht entweder eine Nachricht verloren oder sie wird doppelt zugestellt. Ist die Ausgangs-Queue eine Transaktions-Queue, ist die Mindestanforderung, den MSMQ-Empfang transaktional zu gestalten, sodass sich ein fehlgeschlagenes Schreiben zurückrollen lässt, und die neue Queue so zu entwerfen, dass sie Duplikate anhand der Nachrichten-ID abweisen kann (also idempotent ist). Ist die Ausgangs-Queue nicht transaktional, lässt sich dieser Weg nicht nutzen, weil das Transaktionsattribut einer Queue bei der Erstellung festgelegt wird und sich später nicht ändern lässt. In diesem Fall bauen Sie es in der Reihenfolge „mit Peek lesen → idempotent in die neue Queue schreiben → nach Bestätigung des Schreibens entfernen“ auf (stürzt es vor dem Entfernen ab, fängt die Idempotenz der neuen Queue das Duplikat ab). Lohnt sich keiner der beiden Aufwände für die Größenordnung, ist es sicherer, auf die Brücke zu verzichten und stattdessen auf das „Leerlaufen und Umschalten“ aus Schritt 5 zu setzen.
- Das Verhalten fixieren, bevor Sie umschreiben. Queue-Verarbeitung ist ein Bereich, in dem timing-abhängige Bugs leicht auftreten. Bereiten Sie vor der Migration Charakterisierungstests vor — „bei dieser Eingabenachricht dieses Ergebnis“ —, dann wird die Prüfung nach der Ablösung zu einer mechanischen Übung (siehe „Eine Legacy-Business-Anwendung ohne Tests sicher verändern ── Charakterisierungstests und Refactoring in der Praxis“).
- Umschalten, wenn die Queue leer ist. Ein Umschalten, während noch Nachrichten in der Queue liegen, ist ein Nährboden für doppelte Verarbeitung und Verlust. Die Queue während einer geplanten Auszeit vollständig zu leeren und erst dann umzuschalten, ist letztlich die sicherste und schnellste Methode.
7. Mindestbedingungen, wenn Sie sich für das Belassen im Ist-Zustand entscheiden
Die Entscheidung „es gibt keinen Plan, die Anwendung auf .NET zu heben, und auch das Kosten-Nutzen-Verhältnis spricht vorerst gegen eine Migration“ ist unter Bedingungen vertretbar. Die Mindestbedingungen für diesen Fall führen wir als Checkliste auf, die Sie unverändert in ein Genehmigungs- oder Review-Dokument übernehmen können. Betrachten Sie „Belassen im Ist-Zustand“ erst dann als Option, wenn alle vier Punkte abgehakt sind.
| Prüfung | Mindestbedingung | Konkret zu tun | Was passiert, wenn nicht erfüllt |
|---|---|---|---|
| □ | MSMQ im Kitting-/Restore-Verfahren ausdrücklich festhalten | MSMQ ist ein optionales Windows-Feature. Die Aktivierungsschritte — über „Windows-Features aktivieren oder deaktivieren“ oder DISM/PowerShell — im Aufbauhandbuch der Umgebung dokumentieren | Beim Austausch von PC oder Server wird die Aktivierung vergessen, und am Umstellungstag funktioniert nichts, ohne dass die Ursache erkennbar ist |
| □ | Warteschlangenlänge überwachen | Schwellenwertüberwachung und Benachrichtigung für die Anzahl gestauter Nachrichten einrichten. Dead-Letter- und Journal-Queue mit einbeziehen | Steht die Empfängerseite, gibt es keinen Fehler — die Nachrichten stauen sich einfach weiter, und der Betrieb kommt zum Stillstand, ohne dass es jemand bemerkt |
| □ | Konfiguration dokumentieren | Pfad der Queue, Berechtigungen, ob transaktional, Formatter und Journal-Einstellungen festhalten (die Bestandsaufnahme-Tabelle aus Abschnitt 6 lässt sich direkt verwenden) | Eine künftige Migrationsschätzung muss die Untersuchung von vorn beginnen, was Genauigkeit und Aufwand verschlechtert |
| □ | Die Entscheidung einmal jährlich überprüfen | Jährlich prüfen, ob es auf die Deprecated-Liste gekommen ist und ob sich das Verhalten durch ein OS-Update geändert hat | Man gerät erst nach einer Deprecation-Ankündigung in Hektik |
Der vierte Punkt wird besonders leicht unterschätzt, aber gerade diese jährliche Überprüfung ist es, die dafür sorgt, dass Sie auch nach einer Ankündigung nicht in Hektik geraten. Umgekehrt gilt: Ein Belassen im Ist-Zustand in einer Umgebung, in der sich diese vier Punkte nicht erfüllen lassen, ist dasselbe wie darauf zu warten, dass es unbemerkt stehen bleibt.
8. Zusammenfassung
- MSMQ ist Stand Juli 2026 offiziell nicht deprecated und besteht als Betriebssystemfunktion fort. Die Wahrnehmung „bereits eingestellt“ ist nicht zutreffend.12
- System.Messaging bleibt hingegen ausschließlich auf das .NET Framework beschränkt, ist nicht im Compatibility Pack enthalten, und es gibt keinen offiziellen Weg zu .NET (Core und neuer). CoreWCF selbst besitzt zwar eine Support-Richtlinie, aber dessen MSMQ-Transport hängt von einer Community-Portierung von System.Messaging ab.345
- Die Achse der Entscheidung ist, ob Sie die Anwendung auf .NET heben. Wenn ja, gilt als Grundsatz, die Queue gleich mit zu migrieren (eine Lebensverlängerung per P/Invoke o. Ä. wird gegen die Wartungslast eingetauscht); beim Belassen im Ist-Zustand steht und fällt es mit Monitoring und Dokumentation.6
- Erster Kandidat für das Migrationsziel ist eine Tabellen-Queue in der DB. Im Kern geht es darum, die Konsistenz von MSMQ+DTC durch eine lokale Transaktion zu ersetzen; die Einführung eines Broker-Produkts kommt erst danach in Betracht.
- Eine BinaryFormatter-basierte Serialisierung lässt sich wegen ihrer Entfernung in .NET 9 nicht ins neue System übernehmen. Machen Sie JSON zum Standard bei der Migration, wobei ein unabhängig gepflegtes Format wie protobuf unverändert übernommen werden kann.7
- Das Umschalten in der Reihenfolge Empfängerseite → Brücke → Senderseite, mit einer Fixierung des Verhaltens durch Charakterisierungstests vor dem Umschreiben, ist der Weg, der ohne Zwischenfälle auskommt.
Verwandte Artikel
- Wie lange laufen VB6-Anwendungen noch? — Support-Status der Laufzeitumgebung und ein praxisnaher Weg zur .NET-Migration
- Checkliste vor der Migration von .NET Framework zu .NET
- Eine Legacy-Business-Anwendung ohne Tests sicher verändern ── Charakterisierungstests und Refactoring in der Praxis
- Windows-Prozesskommunikation richtig wählen ── Eine Entscheidungstabelle für Named Pipes / TCP / gRPC / Shared Memory / COM
- Der Irrtum, dass TCP im gleichen Format empfängt, in dem gesendet wurde ── Empfangsdesign für den Umgang mit einem Bytestrom
- Wenn Sie ein System ohne Quellcode und ohne Dokumentation übernehmen — Ein praktisches Playbook, um es am Laufen zu halten
- Das Datenbankschema Ihrer Business-Anwendung versionieren ── Migrationspraxis gegen „jeder Kunde hat eine andere Datenbank“
Verwandte Beratungsleistungen
Die KomuraSoft LLC übernimmt die Bestandsaufnahme und Migrationsplanung für Legacy-Konfigurationen einschließlich MSMQ, die Migration von .NET Framework zu .NET sowie die Überarbeitung von Fachanwendungen mit Queue-Verarbeitung.
- Weiternutzung und Migration von Altbeständen
- Wartung und Weiterentwicklung bestehender Windows-Software
- Windows-Anwendungsentwicklung
- Kontakt
Referenzlinks
-
Microsoft Learn, Deprecated features in the Windows client. Die offizielle Liste der Features, deren aktive Entwicklung im Windows-Client eingestellt wurde (deprecated). Dazu, dass NTLM, VBScript, WordPad und andere auf der Liste vom Juli 2026 stehen, während MSMQ (Microsoft Message Queuing) nicht darauf verzeichnet ist, sowie dazu, dass deprecated eine Stufe ist, in der ein Feature „nicht mehr aktiv entwickelt wird und in einem künftigen Update entfernt werden kann“ — zu unterscheiden von removed (entfernt). ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Features Removed or No Longer Developed in Windows Server. Die offizielle Liste der aus Windows Server entfernten und der nicht mehr weiterentwickelten (deprecated) Features. Dazu, dass MSMQ auf der Liste vom Stand Juli 2026, einschließlich der Registerkarte für Windows Server 2025, nicht verzeichnet ist, sowie dazu, dass deprecated Komponenten weiterhin mit Windows Server ausgeliefert werden, gemäß dem Produktlebenszyklus für den Produktivbetrieb unterstützt bleiben und weiterhin Sicherheits- und Qualitätsupdates erhalten. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, MessageQueue Class (System.Messaging). Dazu, dass die Referenzdokumentation der Klasse System.Messaging.MessageQueue die Versionen .NET Framework 1.1 bis 4.8.1 abdeckt und keine Version für .NET (Core und neuer) existiert. ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, Use the Windows Compatibility Pack to port code to .NET. Dazu, dass das Windows Compatibility Pack (das Paket Microsoft.Windows.Compatibility) rund 20.000 APIs bereitstellt, um Abhängigkeiten von .NET-Framework-exklusiven APIs bei der Migration zu .NET auszugleichen, und dazu, dass seine Liste der Technologiebereiche (CodeDom, Configuration, Directory Services, Drawing, ODBC, ACLs, WCF, Registry, WMI, Performance Counters, Windows-Dienste, EventLog u. a.) kein Messaging (System.Messaging) enthält. ↩ ↩2 ↩3 ↩4
-
CoreWCF project, CoreWCF.MSMQ (NuGet) und CoreWCF 1.4.0 Preview release, Microsoft, CoreWCF Support Policy. Dazu, dass CoreWCF ein community-geführtes Projekt ist, das die Serverseite von WCF nach .NET portiert, wobei Microsoft eine offizielle Support-Richtlinie bereitstellt; dazu, dass als Teil der queue-basierten Transporte MSMQ-Unterstützung (das Paket CoreWCF.MSMQ) veröffentlicht wird; sowie dazu, dass diese MSMQ-Implementierung von einer Community-Portierung der .NET-Framework-Version der System.Messaging-Bibliothek abhängt. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, .NET Framework official support policy. Dazu, dass .NET Framework 4.8 als Komponente des Windows-Betriebssystems definiert ist und gemäß der Lebenszyklus-Richtlinie des installierten übergeordneten Produkts (des Betriebssystems) unterstützt wird. ↩ ↩2 ↩3
-
Microsoft Learn, BinaryFormatter migration guide. Dazu, dass BinaryFormatter aus Sicherheitsgründen schrittweise abgeschafft wird, die Implementierung ab .NET 9 aus der Laufzeit entfernt und standardmäßig nicht mehr nutzbar ist, sowie dazu, dass als Migrationsziel sichere Serialisierungsformate wie JSON (System.Text.Json) empfohlen werden. ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn (Archiv), Express and Recoverable Messaging, System-Generated Queues, Message Queuing (MSMQ). Dazu, dass Express-Nachrichten sowohl während als auch nach der Zustellung im RAM gehalten werden und beim Stoppen des Computers, auf dem sich die Nachricht befindet, oder des MSMQ-Diensts verloren gehen; dazu, dass recoverable Nachrichten beim Sender und auf jedem vermittelnden Computer auf die Festplatte geschrieben und auch in der Zielqueue auf der Festplatte gehalten werden; dazu, dass öffentliche Queues im Verzeichnisdienst registriert werden, während private Queues nur auf dem lokalen Computer registriert und nicht im Verzeichnisdienst veröffentlicht werden; sowie dazu, dass die Journal-Queue, die Kopien aus einer Queue entnommener oder bereits gesendeter Nachrichten hält, und die Dead-Letter-Queue, die nicht zustellbare Nachrichten hält, von MSMQ erzeugte Systemqueues sind. ↩
-
Microsoft Learn (Archiv), Message Queuing Functions und MQSendMessage, MQReceiveMessage. Dazu, dass MSMQs native Win32-API (
MQCreateQueue,MQSendMessage,MQReceiveMessageu. a.) für C/C++-Anwendungen dokumentiert ist und sich Queues damit erstellen, an sie senden und aus ihnen empfangen lassen, ohne über eine Managed API zu gehen. ↩ -
Microsoft Learn, Tabellenhinweise (Transact-SQL). Dazu, dass
READPASTein Hinweis ist, der Zeilen, die von anderen Transaktionen gesperrt sind, überspringt statt sie zu lesen, dass sich damit nur Sperren auf Zeilenebene, nicht auf Seitenebene, überspringen lassen, und dass er sich nur unter den IsolationsstufenREAD COMMITTEDoderREPEATABLE READangeben lässt. Insbesondere zu der Aussage, dass „wenn die DatenbankoptionREAD_COMMITTED_SNAPSHOTaufONgesetzt ist und entweder (a) die Transaktionsisolationsstufe der SitzungREAD COMMITTEDist, oder (b) die Abfrage zusätzlich den TabellenhinweisREADCOMMITTEDangibt, der TabellenhinweisREADPASTnicht angegeben werden kann. Um den HinweisREADPASTin diesen Fällen anzugeben, entfernen Sie den TabellenhinweisREADCOMMITTED, falls vorhanden, und nehmen Sie den TabellenhinweisREADCOMMITTEDLOCKin die Abfrage auf.“ Siehe dieselbe Seite auch dazu, dassREADCOMMITTEDLOCKein Hinweis ist, der unabhängig von der Einstellung vonREAD_COMMITTED_SNAPSHOTein sperrenbasiertesREAD COMMITTEDerzwingt, sowie dazu, dass sich für eine einzelne Tabelle nicht mehr als ein Granularitätshinweis (PAGLOCK/NOLOCK/READCOMMITTEDLOCK/ROWLOCK/TABLOCK/TABLOCKX) angeben lässt. Die datenbankseitige Einstellung lässt sich überis_read_committed_snapshot_onin sys.databases prüfen. ↩ ↩2 -
Microsoft Learn, TOP (Transact-SQL). Dazu, dass bei Verwendung von TOP mit INSERT, UPDATE, MERGE oder DELETE die betroffenen Zeilen nicht in irgendeiner Reihenfolge angeordnet werden, und dazu, eine Unterabfrage mit TOP und ORDER BY zu verwenden, wenn eine Reihenfolge festgelegt werden soll. ↩
Verwandte Artikel
Aktuelle Artikel mit denselben Schlagwörtern führen zu verwandten Themen weiter.
Wie lange laufen VB6-Anwendungen noch? — Support-Status der Laufzeitumgebung und ein praxisnaher Weg zur .NET-Migration
Wie lange laufen VB6-Anwendungen noch? Dieser Artikel ordnet die Asymmetrie zwischen der Support-Richtlinie für die VB6-Laufzeitumgebung ...
Praktische Best Practices für Multithreading: .NET-Edition — Was Sie entscheiden sollten, bevor Sie weitere Threads hinzufügen
Eine praxisnahe Übersicht der Entwurfsregeln, die verhindern, dass Multithreading-Code in .NET/C# gelegentlich abstürzt oder hängen bleib...
WMI/CIM aus C# und PowerShell verwenden — Praxisleitfaden für Hardwareinformationen, Prozessüberwachung und Remoteabfragen
WMI/CIM ist die Standardlösung, um die Seriennummer eines PCs auszulesen, freien Festplattenspeicher zu überwachen und den Start von Proz...
Abwärtskompatibilität von DLL- und COM-Schnittstellen — Eine Entscheidungstabelle dafür, welche Änderungen Aufrufer brechen
Welche Änderungen an einer DLL oder COM-Komponente brechen tatsächlich deren Aufrufer? Wir legen die drei Ebenen der Kompatibilität dar —...
Das Datenbankschema Ihrer Business-Anwendung versionieren ── Migrationspraxis gegen „jeder Kunde hat eine andere Datenbank“
Ein praktischer Leitfaden zur Versionierung des Datenbankschemas einer Business-Anwendung, deren Datenbanken über zahlreiche Kundenstando...
Verwandte Themen
Diese Seiten ordnen den Artikel in einen größeren Leistungs- und Entscheidungskontext ein.
Technische Windows-Themen
Portal zu Windows-Entwicklung, Fehleranalyse und der Nutzung bestehender Assets.
Leistungen zu diesem Thema
Dieser Artikel ist direkt mit den folgenden Leistungen verbunden.
Windows-App-Entwicklung
Geschäftsanwendungen, Geräteintegration und Kommunikationstools von den Anforderungen bis zur Umsetzung.
Wartung und Modernisierung von Windows-Software
Funktionserweiterungen, Wartung und schrittweise Modernisierung bestehender Windows-Software.
Häufige Fragen
Fragen, die in Beratungen zu diesem Artikelthema häufig gestellt werden.
- Wurde MSMQ eingestellt?
- Nein. Stand Juli 2026 taucht MSMQ weder in der Liste der deprecated Features des Windows-Clients noch in der Windows-Server-Liste „Entfernte Features / nicht mehr weiterentwickelte Features“ auf. Es wird nach wie vor als optionales Windows-Feature mit den aktuellen Betriebssystemversionen ausgeliefert. Dass sich die Behauptung „eingestellt“ trotzdem verbreitet hat, liegt daran, dass sie mit der Situation auf der .NET-Seite verwechselt wird. System.Messaging, die Standardklassenbibliothek für den Umgang mit MSMQ, existiert nur im .NET Framework und wurde nie auf .NET (Core und neuer) portiert. Genau genommen gilt also: Als Betriebssystemfunktion besteht es fort, aber es gibt keinen offiziellen Weg, es aus modernem .NET zu nutzen.
- Gibt es keinen Weg, MSMQ aus .NET 8 oder .NET 10 zu nutzen?
- Es gibt keine offizielle Managed API. System.Messaging ist eine API bis .NET Framework 4.8.1 und ist auch nicht im Windows Compatibility Pack (Microsoft.Windows.Compatibility) enthalten. Die native Win32-API von MSMQ (etwa MQSendMessage) per P/Invoke aufzurufen, ist technisch möglich, bedeutet aber, den Bau und die Pflege eines eigenen Wrappers samt Formatter und Transaktionsanbindung zu übernehmen. Auf der Community-Seite veröffentlicht das CoreWCF-Projekt ein Paket für den MSMQ-Transport (CoreWCF.MSMQ), aber das dient dazu, über eine Queue aufgerufene WCF-Dienste auf modernem .NET zu hosten (eine Portierung der Serverseite von WCF) — es ist weder eine allgemeine Queue-API als Ersatz für System.Messaging noch ein Ersatz für den sendenden Client. Die Implementierung hängt zudem von einer Community-Portierung des System.Messaging der .NET-Framework-Version ab. Für Evaluierung oder eine vorübergehende Lebensverlängerung ist es eine gangbare Option. CoreWCF selbst besitzt eine offizielle Support-Richtlinie von Microsoft, doch diese Garantie erstreckt sich nicht automatisch auf die Community-Portierung von System.Messaging, von der diese MSMQ-Implementierung abhängt. Wenn Sie ein Produktivsystem darauf aufbauen wollen, sollten Sie deshalb erst prüfen, ob die verwendete Version unter die Support-Richtlinie fällt und wie mit dem abhängigen Teil umgegangen wird. In der Praxis ist es der richtige Weg, die Queue zu demselben Zeitpunkt zu migrieren, zu dem Sie die Anwendung auf .NET heben.
- Was eignet sich besser als Migrationsziel — RabbitMQ oder Azure Service Bus?
- Bevor Sie sich zwischen den beiden entscheiden, prüfen Sie zunächst, ob sich eine Datenbanktabelle als Queue eignet. Bei den meisten kleinen und mittleren Fachanwendungen, die MSMQ verwenden, ist die Gegenstelle der Queue ein Prozess, der die eigene Datenbank aktualisiert. In diesem Fall lässt sich mit einer Tabellen-Queue „das Entnehmen der Nachricht“ und „die Aktualisierung der Geschäftsdaten“ in derselben lokalen Transaktion wie die Geschäftsdaten festschreiben — das ersetzt die Konsistenz, die MSMQ zusammen mit einer verteilten Transaktion (DTC) geliefert hat, durch einen deutlich einfacheren Mechanismus. Erst wenn eine Tabellen-Queue für eine Anforderung nicht ausreicht — etwa lose gekoppelte Zustellung zwischen mehreren Systemen oder ein Bedarf an hohem Durchsatz —, sollten Sie RabbitMQ in Betracht ziehen, falls die Anforderung stark On-Premises geprägt ist, oder Azure Service Bus, falls sich das in die Cloud verlagern lässt. Diese Reihenfolge scheitert am seltensten.
- Ist die Entscheidung vertretbar, vorerst bei .NET Framework zu bleiben und es unangetastet zu lassen?
- Unter Bedingungen: ja. .NET Framework 4.8 wird als Windows-Komponente entlang des Lebenszyklus des Betriebssystems unterstützt, und auch MSMQ selbst ist nicht deprecated, sodass Sie realistisch davon ausgehen können, dass es „weiterläuft“. Wenn Sie sich trotzdem für das unangetastete Belassen entscheiden, sollten Sie mindestens diese vier Dinge tun: die Aktivierung des MSMQ-Features im Kitting-Verfahren ausdrücklich festhalten, eine Überwachung von Warteschlangenlänge und Journal einrichten, Nachrichtenformat und Verbindungskonfiguration dokumentieren, sowie ein Wiederherstellungsverfahren hinterlegen, falls der zuständige Mitarbeiter wechselt. Das eigentliche Risiko des unangetasteten Belassens ist nicht technischer Natur — es ist, dass niemand mehr da ist, der sich damit auskennt.
Autorenprofil
Profilseite des Artikelautors.
Go Komura
Geschäftsführer von KomuraSoft LLC
Spezialisiert auf Windows-Softwareentwicklung, technische Beratung und Fehleranalyse, insbesondere bei bestehenden Systemen und schwer reproduzierbaren Störungen.