it-swarm.it

L'inserimento di dati in SQL Server blocca l'intera tabella?

Sto usando Entity Framework , e sto inserendo record nel nostro database che includono un campo blob. Il campo blob può contenere fino a 5 MB di dati.

Quando inserisci un record in questa tabella, blocca l'intera tabella?

Quindi, se stai interrogando qualsiasi dato dalla tabella, bloccherà fino a quando l'inserimento non sarà completato (mi rendo conto che ci sono dei modi per aggirare questo problema, ma sto parlando per impostazione predefinita)?

Quanto ci vorrà prima che causi un deadlock? Questo tempo dipenderà dalla quantità di carico presente sul server, ad es. se non c'è molto carico, ci vorrà più tempo per causare un deadlock?

C'è un modo per monitorare e vedere cosa è bloccato in un determinato momento?

Se ogni thread esegue query su singole tabelle, esiste un caso in cui può verificarsi il blocco? Quindi non è il caso che un deadlock può verificarsi solo se hai una query che ha un join e agisce su più tabelle?

Ciò sta tenendo conto del fatto che la maggior parte del mio codice è solo un insieme di istruzioni selezionate, non un mucchio di transazioni a lungo termine o qualcosa del genere.

47
peter

Santa mucca, hai un sacco di domande qui, eh. Ecco alcune risposte:

Quando si inserisce un record in questa tabella, blocca l'intera tabella?

Non per impostazione predefinita, ma se si utilizza l'hint TABLOCK o se si eseguono determinati tipi di operazioni di caricamento di massa, allora sì.

Quindi se stai interrogando qualsiasi dato dalla tabella lo bloccherà fino a quando l'inserimento non sarà completato (mi rendo conto che ci sono dei modi per aggirare questo, ma sto parlando per impostazione predefinita)?

Questo diventa un po 'più complicato. Se qualcuno sta provando a selezionare i dati da una pagina nella tabella che hai bloccato, allora sì, li blocchi. È possibile aggirare il problema con cose come l'hint NOLOCK su un'istruzione select o usando l'isolamento di snapshot Committed Read. Per un punto di partenza su come funzionano i livelli di isolamento, controlla Poster di livelli di isolamento di Kendra Little .

Quanto ci vorrà prima che causi un deadlock? Questo tempo dipenderà dalla quantità di carico presente sul server, ad es. se non c'è molto carico ci vorrà più tempo per causare un deadlock?

I deadlock non sono basati sul tempo: si basano sulle dipendenze. Diciamo che abbiamo questa situazione:

  • Query A sta tenendo un mucchio di serrature e, per completare la sua query, ha bisogno di tutto ciò che è bloccato da Query B
  • Query B sta anche tenendo un mucchio di serrature e, per completare la sua query, ha bisogno di cose che sono bloccate dalla Query A

Nessuna query può andare avanti (si pensi al blocco messicano), quindi SQL Server lo chiama, disegna la query di qualcuno nella parte posteriore, rilascia i blocchi e lascia andare l'altra query. SQL Server sceglie la vittima in base alla quale sarà meno costoso eseguire il rollback. Se si vuole essere fantasiosi, è possibile utilizzare SET DEADLOCK_PRIORITY LOW su particolari query per dipingere i target sulla loro schiena e SQL Server li scatterà per primi.

C'è un modo per monitorare e vedere cosa è bloccato in un determinato momento?

Assolutamente - ci sono le viste di gestione dinamica (DMV) che puoi interrogare come sys.dm_tran_locks, ma il modo più semplice è usare il proc memorizzato gratuito di Adam Machanic sp_WhoIsActive . Si tratta di un vero e proprio sostituto per sp_who che puoi chiamare così:

sp_WhoIsActive @get_locks = 1

Per ogni query in esecuzione, otterrai un piccolo XML che descrive tutti i blocchi che contiene. C'è anche una colonna di blocco, quindi puoi vedere chi sta bloccando chi. Per interpretare i blocchi che si stanno tenendo, ti consigliamo di controllare le descrizioni di Books Online dei tipi di blocco .

Se ogni thread esegue query su singole tabelle, esiste un caso in cui può verificarsi il blocco? Quindi non è il caso che un deadlock può verificarsi solo se hai una query che ha un join e agisce su più tabelle?

Che ci crediate o meno, una singola query può effettivamente bloccarsi , e sì, le query possono bloccarsi su una sola tabella. Per saperne di più su deadlock, controlla The Difficulty with Deadlocks di Jeremiah Peschka .

114
Brent Ozar

Se hai il controllo diretto su SQL, puoi forzare il blocco a livello di riga usando:

INSERT INTO MyTable(Id, BigColumn) WITH (ROWLOCK)
VALUES(...)

Queste due risposte potrebbero essere utili:

È possibile forzare il blocco a livello di riga in SQL Server?

Blocco di una tabella con una selezione in Entity Framework

Per visualizzare i blocchi bloccati correnti in Management Studio, guardare sotto il server, quindi sotto Gestione/Monitoraggio attività. Ha una sezione per i blocchi per oggetto, quindi dovresti essere in grado di vedere se gli inserti causano davvero un problema.

3
Andrew Bain

Gli errori di deadlock generalmente ritornano abbastanza rapidamente. Gli stati di deadlock non si verificano a causa di un errore di timeout durante l'attesa di un blocco. Deadlock viene rilevato da SQL Server cercando i cicli nelle richieste di blocco.

0
Timothy Klenke

La migliore risposta che posso dare è: dipende.

Il modo migliore per verificare è trovare la tua connessione SPID e utilizzare sp_lock SPID per verificare se la modalità di blocco è X sul tipo di TAB. Puoi anche verificare il nome della tabella con SELECT OBJECT_NAME(objid). Mi piace anche usare la query qui sotto per verificare il blocco.

    SELECT RESOURCE_TYPE,RESOURCE_SUBTYPE,DB_NAME(RESOURCE_DATABASE_ID) AS 'DATABASE',resource_database_id DBID,
    RESOURCE_DESCRIPTION,RESOURCE_ASSOCIATED_ENTITY_ID,REQUEST_MODE,REQUEST_SESSION_ID,
    CASE WHEN RESOURCE_TYPE = 'OBJECT' THEN OBJECT_NAME(RESOURCE_ASSOCIATED_ENTITY_ID,RESOURCE_DATABASE_ID) ELSE '' END OBJETO
    FROM SYS.DM_TRAN_LOCKS (NOLOCK)
    WHERE REQUEST_SESSION_ID = --SPID here

In SQL Server 2008 (e versioni successive) è possibile disattivare l'escalation dei blocchi sulla tabella e imporre un WITH (ROWLOCK) nella clausola insert forzando in modo efficace un rowlock. Non è possibile eseguire ciò prima di SQL Server 2008 (è possibile scrivere WITH ROWLOCK, ma SQL Server può scegliere di ignorarlo).

Sto parlando di generali qui, e non ho molta esperienza con i BLOB perché di solito consiglio agli sviluppatori di evitarli, specialmente se sono più grandi di 1 MB.

0
Thiago Dantas