Es un novato en el trabajo de DB, así que aprecia tu paciencia con una pregunta básica. Estoy ejecutando SQL Server 2014 en mi máquina local, y tengo una pequeña tabla y una aplicación cliente básica para probar diferentes enfoques. Me estoy poniendo lo que parece ser un bloqueo de tabla durante tanto INSERT INTO
y UPDATE
declaraciones. El cliente es una aplicación ASP.NET con el siguiente código:
OleDbConnection cn = new OleDbConnection("Provider=SQLNCLI11; server=localhost\\SQLEXPRESS; Database=<my db>; user id=<my uid>; password=<my pwd>");
cn.Open();
OleDbTransaction tn = cn.BeginTransaction();
OleDbCommand cmd = new OleDbCommand("INSERT INTO LAYOUTSv2 (LAYOUTS_name_t, LAYOUTS_enabled_b, LAYOUTS_data_m) VALUES ('name', '-1', 'data')", cn, tn);
cmd.ExecuteNonQuery();
cmd.CommandText = "SELECT SCOPE_IDENTITY()";
int newkey = Decimal.ToInt32((decimal)cmd.ExecuteScalar());
Console.WriteLine("Created index " + newkey);
Thread.Sleep(15000);
tn.Commit();
tn = cn.BeginTransaction();
cmd.CommandText = "UDPATE LAYOUTSv2 SET LAYOUTS_enabled_b='-3' WHERE LAYOUTS_key='" + newkey + "'";
cmd.Transaction = tn;
cmd.ExecuteNonQuery();
Console.WriteLine("updated row");
Thread.Sleep(15000);
tn.Rollback();
cn.Close();
Ejecuto este código, luego desde el estudio de administración que ejecuto SELECT * FROM LAYOUTSv2
. Durante ambos casos, cuando el hilo del cliente está en pausa (es decir, antes de la confirmación / reversión), la consulta SELECT se bloquea hasta que se produce la confirmación / reversión.
La tabla tiene el campo LAYOUTS_key asignado como clave principal. En la ventana de propiedades muestra que es único y está agrupado, con bloqueos de página y bloqueos de fila permitidos. La configuración de escalado de bloqueo para la tabla es Desactivar ... He probado las otras configuraciones disponibles de Tabla y AUTO sin cambios. Lo intenté SELECT ... WITH (NOLOCK)
y eso arroja un resultado de inmediato, pero como está bien advertido aquí y en otros lugares, no es lo que debería estar haciendo. He intentado poner la ROWLOCK
pista en las declaraciones INSERT
y UPDATE
, pero nada ha cambiado.
El comportamiento que estoy buscando es el siguiente: antes de confirmar un INSERT
, las consultas de otros subprocesos leen todas las filas, excepto la que se está INSERT
editando. Antes de confirmar una UPDATE
consulta de otros hilos, lea la versión inicial de la fila que se está UPDATE
editando. ¿Hay alguna manera de que pueda hacer esto? Si necesito proporcionar otra información para aclarar mi caso de uso, hágamelo saber. Gracias.
newkey
" something';DELETE FROM LAYOUTSv2 --
". Su actualización se completará con éxito y luego vaciará la tabla porque el usuario manipuló la consulta insertando un apóstrofe. Normalmente, una consulta parametrizada se parece a algo así UDPATE LAYOUTSv2 SET LAYOUTS_enabled_b='-3' WHERE LAYOUTS_key=?
, después de lo cual asigna valores por separado al ?
(parámetro) en su código.
WHERE LAYOUTS_key='" + newkey + "'
es un no-no completo por varias razones, incluida la inyección de SQL, debe usar consultas parametrizadas.