SQL Server Insertar consulta para un foro
-
08-10-2019 - |
Pregunta
Teniendo en cuenta una mesa foro y muchos usuarios al mismo tiempo la inserción de mensajes en él, qué tan seguro es esta transacción?
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION
DECLARE @LastMessageId SMALLINT
SELECT @LastMessageId = MAX(MessageId)
FROM Discussions
WHERE ForumId = @ForumId AND DiscussionId = @DiscussionId
INSERT INTO Discussions
(ForumId, DiscussionId, MessageId, ParentId, MessageSubject, MessageBody)
VALUES
(@ForumId, @DiscussionId, @LastMessageId + 1, @ParentId, @MessageSubject, @MessageBody)
IF @@ERROR = 0
BEGIN
COMMIT TRANSACTION
RETURN 0
END
ROLLBACK TRANSACTION
RETURN 1
Aquí leí última MessageId y se incrementará. No puedo utilizar el campo de identidad ya que tiene que ser incrementado por cada mensaje se inserta en un grupo (no todos los mensajes de inserción en la tabla.)
Solución
La transacción debe ser bastante segura de hecho - echa un vistazo a los documentos MSDN en el SERIALIZABLE nivel de transacción :
SERIALIZABLE
especifica lo siguiente:
Declaraciones no pueden leer los datos que han sido modificados , pero aún no cometido por otras transacciones.
No hay otras transacciones pueden modificar los datos que ha sido leído por el transacción actual hasta que la corriente la transacción termine.
Otras operaciones no puede insertar nuevas filas con valores clave que caería en el rango de teclas leer por cualquier declaración en el actual transacción hasta que la corriente la transacción termine.
bloqueos de intervalo se sitúan en el rango de los valores clave que coinciden con el condiciones de cada sentencia de búsqueda ejecutado en una transacción. esto bloquea otras operaciones de actualización o la inserción de las filas que se califica para cualquiera de las declaraciones realizadas por la transacción actual. Esto significa que si alguna de las declaraciones en una transacción se ejecuta una segunda tiempo, que van a leer el mismo conjunto de filas. Los bloqueos de intervalo se mantienen hasta se complete la transacción. Este es el más restrictivo del aislamiento los niveles, ya que entrelaza rangos enteros de llaves y mantiene los bloqueos hasta que el la transacción termine. Porque concurrencia es menor, utilice esta opción Solo cuando sea necesario. Esta opción tiene el mismo efecto que establecer en HOLDLOCK todas las tablas de todas las instrucciones SELECT en una transacción.
El problema principal con este nivel de aislamiento es que es una carga pesada bastante en el servidor, y serializa (como su nombre indica) cualquier acceso, por lo que su rendimiento del servidor y la escalabilidad van a sufrir, por ejemplo, con un número muy elevado de usuarios, que posiblemente va a obtener una gran cantidad de tiempos de espera para los usuarios que esperan para una transacción a fin.
Así, utilizando el enfoque más ligero de un mensaje de identificación global como INT IDENTITY
es definitivamente mucho mejor!