Estoy usando SQL Server 2005 Express.
En un escenario, agregué un Begin Transaction
comando justo antes de una INSERT
declaración en un procedimiento almacenado. Cuando ejecuté este procedimiento almacenado, bloqueó toda la tabla y todas las conexiones concurrentes mostraron una pantalla bloqueada hasta el momento en que esto INSERT
terminó.
¿Por qué se bloquea toda la tabla y cómo supero este problema en SQL Server 2005 Express?
Editado
La consulta es la siguiente:
INSERT INTO <table2> SELECT * FROM <table1> WHERE table1.workCompleted = 'NO'
Respuestas:
Esta respuesta puede resultar útil para la pregunta original, pero es principalmente para abordar información inexacta en otras publicaciones. También destaca una sección de tonterías en BOL.
La sección vinculada de BOL establece:
NB: A partir de 2014-8-27, BOL se ha actualizado para eliminar las declaraciones incorrectas citadas anteriormente.
Afortunadamente este no es el caso. Si fuera así, las inserciones en una tabla ocurrirían en serie y todos los lectores quedarían bloqueados de toda la tabla hasta que se complete la transacción de inserción. Eso haría que SQL Server sea un servidor de base de datos tan eficiente como NTFS. No muy.
El sentido común sugiere que no puede ser así, pero como señala Paul Randall, " Hazte un favor, no confíes en nadie ". Si no puede confiar en nadie, incluido BOL , supongo que tendremos que demostrarlo.
Cree una base de datos y complete una tabla ficticia con un montón de filas, observando que se devuelve el DatabaseId.
Configure un seguimiento del generador de perfiles que rastreará los eventos de bloqueo: adquiridos y bloqueados: liberados, filtrando en el DatabaseId del script anterior, configurando una ruta para el archivo y observando el TraceId devuelto.
Inserte una fila y detenga la traza:
Abra el archivo de rastreo y debería encontrar lo siguiente:
La secuencia de bloqueos tomados es:
Los bloqueos se liberan en orden inverso. En ningún momento se ha adquirido un candado exclusivo sobre la mesa.
Sí lo es. SQL Server (y posiblemente cualquier motor de base de datos relacional) no tiene previsión sobre qué otros lotes pueden estar ejecutándose cuando procesa una declaración y / o lote, por lo que la secuencia de adquisición de bloqueo no varía.
Para este ejemplo particular, se toman exactamente los mismos bloqueos. ¡No confíes en mí, pruébalo!
fuente
No hago mucho trabajo T-SQL pero al leer la documentación ...
Esto es por diseño, como se indica en COMENZAR TRANSACCIÓN :
Y como se indica para la documentación de INSERT , adquirirá un bloqueo exclusivo sobre la mesa. La única forma en que se puede hacer un SELECT contra la tabla es usar
NOLOCK
o establecer el nivel de aislamiento de la transacción.fuente