2008-10-24 14 views
58

Wie lange sollte es dauernWie lange sollte SET READ_COMMITTED_SNAPSHOT ON dauern?

ALTER DATABASE [MySite] SET READ_COMMITTED_SNAPSHOT ON 

ich es gerade lief laufen und es wird 10 Minuten genommen.

Wie kann ich überprüfen, ob es angewendet wird?

+1

hat es jemals fertig? –

+21

lassen Sie mich überprüfen ... –

+0

oops. war die ganze Zeit nicht aktiviert !! (Ernst!) Das erklärt die Deadlocks. Sehen Sie meine Antwort unten für die vollständigen Ergebnisse und ein besseres Skript zum Ausführen –

Antwort

54

Sie können den Status der Einstellung READ_COMMITTED_SNAPSHOT mithilfe der Ansicht sys.databases überprüfen. Überprüfen Sie den Wert der Spalte is_read_committed_snapshot_on. Bereits asked and answered.

In der Onlinedokumentation wird für die Dauer angegeben, dass keine anderen Verbindungen zur Datenbank möglich sind, wenn dies stattfindet, jedoch kein Einzelbenutzermodus erforderlich ist. Sie können also durch andere aktive Verbindungen blockiert werden. Führen Sie sp_who (oder sp_who2) aus, um zu sehen, was noch mit dieser Datenbank verbunden ist.

+0

danke. Es dauert 40 Minuten bis jetzt und zeigt 0 an. Es ist eine 740mb Datenbank. Daumen drücken ich habe es nicht gebrochen –

+3

Versuchen Sie, ein anderes Abfragefenster gegen diese Datenbank zu öffnen. Wenn Sie können, dann erwarte ich, dass Ihre Anweisung noch nicht gestartet wurde. – Rick

+3

Yup. Es sollte nur ein paar Sekunden in den meisten Datenbanken dauern. Wenn es länger dauert, wartet es hinter einer anderen (sogar nicht aktiven) Verbindung, um zu beenden, bevor es die Änderung vornehmen kann. Also müssen Sie möglicherweise alle aktuell verbundenen Spids finden und KILLEN (nachdem Sie bewertet haben, was sie tun). DANN sollte es schnell gehen. –

33

Try this:

ALTER DATABASE generic SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE 
+2

Also was ist die Verwendung von "WITH ROLLBACK IMMEDIATE"?bedeutet das, dass es automatisch zurückgesetzt wird, wenn die Abfrage fehlgeschlagen ist? –

+4

Nein, "WITH ROLLBACK IMMEDIATE" bedeutet, dass sofort alle offenen Transaktionen zurückgesetzt werden, bevor die ALTER DATABASE-Anweisung gestartet wird. Ich rate davon ab, wenn Sie bereits überprüft haben, welche Transaktionen offen sind und ob sie sicher zurückgerollt werden können. – Rick

+0

Danke! arbeitet jetzt sehr schnell. –

8

diesen Code Versuchen:

if(charindex('Microsoft SQL Server 2005',@@version) > 0) 
begin 
    declare @sql varchar(8000) 
    select @sql = ' 
    ALTER DATABASE ' + DB_NAME() + ' SET SINGLE_USER WITH ROLLBACK IMMEDIATE ; 
    ALTER DATABASE ' + DB_NAME() + ' SET READ_COMMITTED_SNAPSHOT ON; 
    ALTER DATABASE ' + DB_NAME() + ' SET MULTI_USER;' 

    Exec(@sql) 
end 
+0

Das hat bei mir funktioniert. (Ich hatte das gleiche Problem) –

+0

Sie sollten Ihre db_name() -Aufrufe mit quoteename() umbrechen, um alle Zeichen im Datenbanknamen zu berücksichtigen, die möglicherweise (wie Leerzeichen) entkommen müssen. – Rick

+0

Sie brauchen auch 'SET allow_snapshot_isolation ON' richtig? (siehe meine Antwort) –

2

Ausprobieren Verwenden Master-Datenbank vor aktuelle Datenbank zu ändern.

USE Master 
GO 

ALTER DATABASE [YourDatabase] SET READ_COMMITTED_SNAPSHOT ON 
GO 
2

Ich habe keine Sekunde für mich nehmen, wenn ich meine DB auf einzelne Benutzer geändert

20

OK (ich bin der ursprüngliche Frages) so stellt sich die ganze Zeit aus habe ich nicht einmal das haben Darn Ding aktiviert.

Hier ist der ultimate code zu laufen, um Snapshot-Modus zu aktivieren und sicherzustellen, dass es aktiviert ist.

SELECT is_read_committed_snapshot_on, snapshot_isolation_state_desc,snapshot_isolation_state FROM sys.databases WHERE name='shipperdb' 

ALTER DATABASE shipperdb SET allow_snapshot_isolation ON 
ALTER DATABASE shipperdb SET SINGLE_USER WITH ROLLBACK IMMEDIATE 
ALTER DATABASE shipperdb SET read_committed_snapshot ON 
ALTER DATABASE shipperdb SET MULTI_USER 

SELECT is_read_committed_snapshot_on, snapshot_isolation_state_desc,snapshot_isolation_state FROM sys.databases WHERE name='shipperdb' 

Dies funktioniert auch mit aktiven Verbindungen (vermutlich geht es ihnen gut, wenn sie rausgeschmissen werden).

Sie können den Status Vorher und Nachher sehen, und dieser sollte fast sofort ausgeführt werden.


WICHTIG:

Die Option READ_COMMITTED_SNAPSHOT oben IsolationLevel.ReadCommitted in .NET entspricht
Die Option ALLOW_SNAPSHOT_ISOLATION oben IsolationLevel.Snapshot in .NET entspricht

Great article about different versioning


.NET-Tipps:

Scheinbar ist Isolationlevel.ReadCommitted im Code erlaubt, auch wenn nicht von der Datenbank aktiviert. Es wird keine Warnung ausgegeben. Also tun Sie sich einen Gefallen und stellen Sie sicher, dass es eingeschaltet ist, bevor Sie annehmen, dass es für 3 Jahre ist, wie ich es tat !!!Wenn Sie C# verwenden, möchten Sie wahrscheinlich ReadCommitted IsolationLevel und nicht Snapshot - es sei denn, Sie schreiben in dieser Transaktion.

READ COMMITTED SNAPSHOT macht optimistische liest und pessimistische schreibt. Im Gegensatz dazu macht SNAPSHOT optimistische Lesevorgänge und optimistische Schreibvorgänge. (from here)

bool snapshotEnabled = true; 

using (var t = new TransactionScope(TransactionScopeOption.Required, 
       new TransactionOptions 
{ 
    IsolationLevel = IsolationLevel.ReadCommitted 
})) 
{ 
    using (var shipDB = new ShipperDBDataContext()) 
    { 

    } 
} 

In weiteren können Sie einen Fehler zu ‚nicht in der Lage zu fördern‘ eine Transaktion zu sein. Suchen Sie nach 'Aktion' in Introducing System.Transactions in the .NET Framework 2.0.

Wenn Sie nicht etwas Spezielles wie zum Beispiel eine Verbindung zu einer externen Datenbank (oder einer zweiten Datenbank) machen, kann das so einfach sein wie das Erstellen eines neuen DataContext. Ich hatte einen Cache, der bei der Initialisierung seinen eigenen Datenkontext "hochspulte" und dabei versuchte, die Transaktion zu einem vollständig verteilten zu eskalieren.

Die Lösung war einfach:

 using (var tran = new TransactionScope(TransactionScopeOption.Suppress)) 
     { 
      using (var shipDB = new ShipperDBDataContext()) 
      { 
       // initialize cache 
      } 
     } 

Siehe auch Deadlocked article by @CodingHorror

+3

Ich wollte erwähnen, da ich mir nicht sicher war: Sie ** können 'READ_COMMITTED_SNAPSHOT' unabhängig von' ALLOW_SNAPSHOT_ISOLATION' einschalten **. Sie können 'ALLOW_SNAPSHOT_ISOLATION' ** off ** haben und trotzdem von' READ_COMMITTED_SNAPSHOT' profitieren, das ** on ** ist. Getestet: Microsoft SQL Server 2012 - 11.0.2100.60 –

+1

Diese Option ändert die Art, wie READ COMMITTED implementiert wird. Wenn diese Option deaktiviert ist, verwendet SQL Server Sperren, um den Zugriff zu steuern. Aus diesem Grund hat Ihr .NET-Code keine Warnung generiert - Sie haben immer noch das Verhalten, nur in einer anderen (und eher zu Deadlock) Weise getan. – Richard

0

Versuchen Sie, die anderen SQL-Dienste, so dass nur der SQL-Server-Dienst ausgeführt werden absperren.

Mine lief für 5 Minuten, dann stornierte ich es, weil es offensichtlich war, dass nichts geschah. Es ist ein brandneuer Server, so dass keine anderen Benutzer verbunden sind. Ich schloss die SQL Reporting Services ab und führte sie erneut aus. Es dauerte weniger als eine Sekunde.

1

habe ich versucht, den Befehl:

ALTER DATABASE MyDB SET READ_COMMITTED_SNAPSHOT ON 
GO 

gegen eine Dev-Box, aber das dauerte es 10+ Minuten und ich es so getötet.

fand ich dann das:

https://willwarren.com/2015/10/12/sql-server-read-committed-snapshot/

und nutzte seine Code-Block (der etwa 1.26 nahm zu laufen):

USE master 
GO 

/** 
* Cut off live connections 
* This will roll back any open transactions after 30 seconds and 
* restricts access to the DB to logins with sysadmin, dbcreator or 
* db_owner roles 
*/ 
ALTER DATABASE MyDB SET RESTRICTED_USER WITH ROLLBACK AFTER 30 SECONDS 
GO 

-- Enable RCSI for MyDB 
ALTER DATABASE MyDB SET READ_COMMITTED_SNAPSHOT ON 
GO 

-- Allow connections to be established once again 
ALTER DATABASE MyDB SET MULTI_USER 
GO 

-- Check the status afterwards to make sure it worked 
SELECT is_read_committed_snapshot_on 
FROM sys.databases 
WHERE [name] = 'MyDB '