2013-08-04 15 views
6

Aggiorno una riga di una tabella, usando WITH (ROWLOCK), ma eseguendo "sp_lock" posso vedere che l'intera tabella è bloccato. Pertanto, prima che la transazione venga eseguita, altre transazioni non possono aggiornare le altre righe della tabella. perché "WITH (ROWLOCK)" non ha effetto?perché l'intera tabella è bloccata mentre "con (rowlock)" è usato in una dichiarazione di aggiornamento

Sto usando la query di seguito con scalmo:

DELETE FROM DefDatabaseSession WITH (ROWLOCK) WHERE ProcessName='test'; 

nel contempo da qualsiasi altra operazione che esegue la stessa operazione di eliminazione per la riga differenza nella stessa tabella io sono sempre l'eccezione

[ Driver JDBC SQLServer] [SQLServer] Periodo di timeout della richiesta di blocco superato .; l'eccezione nidificata è java.sql.SQLException: [newscale] [Driver JDBC SQLServer] [SQLServer] Periodo di timeout della richiesta di blocco superato: com.newscale.bfw.udkernel.kernel.UdKernelException: udconfig.defdbsession.delete; SQLException non categorizzato per SQL [DELETE FROM DefDatabaseSession WHERE ProcessName =?]; Stato SQL [HY000]; codice di errore [1222]; [newscale] [Driver JDBC SQLServer] [SQLServer] Periodo di timeout della richiesta di blocco superato .; l'eccezione nidificata è java.sql.SQLException: [newscale] [Driver JDBC SQLServer] [SQLServer] Periodo di timeout della richiesta di blocco superato.

risposta

2

Il motivo è che l'ottimizzatore ignora il suggerimento di blocco riga [WITH (ROWLOCK) fornisce un suggerimento di query all'ottimizzatore]. Ciò si verifica in situazioni in cui si colpisce un numero molto elevato di righe, in tali scenari l'ottimizzatore trova più fattibile per l'analisi della scansione sulla tabella e quindi il blocco della tabella.

Per una discussione dettagliata si può andare a questo link: http://social.msdn.microsoft.com/Forums/sqlserver/en-US/60238304-04e8-4f98-84d1-3ddf1ed786a9/why-the-entire-table-is-locked-while-with-rowlock-is-used-in-a-update-statement

0

La mia ipotesi è che non si dispone di un indice su ProcessName, quindi la query deve fare una scansione completa della tabella, in tal modo tutte le righe vengono letti (e sono possibili candidati per la cancellazione), quindi è più efficiente bloccare l'intera tabella piuttosto che bloccare ogni riga.

Prova la definizione di un indice:

CREATE INDEX DefDatabaseSession_ProcessName ON DefDatabaseSession(ProcessName); 

Si può scoprire il piano di query facendo una spiegare:

EXPLAIN DELETE FROM DefDatabaseSession WITH (ROWLOCK) WHERE ProcessName='test'; 
+1

'EXPLAIN' non significa esiste in SQL Server. Utilizza il pulsante "includi piano di esecuzione effettivo" per ottenere il piano. – Alejandro

+0

Ho un indice per la colonna ProcessName. – vani

+0

ma ho bisogno del blocco di riga solo ... perché ci sono altre righe che la cancellazione avverrà nello stesso momento da altri thread .. quindi ho bisogno di perdere solo i miei roes non tutti..so non posso usare il lock da tavolo – vani

Problemi correlati