Insérez requête SQL Server pour un forum
-
08-10-2019 - |
Question
Considérant une table de forum et de nombreux utilisateurs simultanément des messages dans l'insertion, comment la sécurité est cette transaction?
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
Ici je lis la dernière MessageId et incrémenter. Je ne peux pas utiliser le champ Identity car il doit être incrémentée pour chaque message inséré dans un groupe (pas tous d'insertion de messages dans la table.)
La solution
Votre transaction devrait être tout à fait sûr en effet - consultez les MSDN docs sur le SERIALIZABLE niveau de transaction :
SERIALIZABLE
Indique les éléments suivants:
Déclarations ne peuvent pas lire les données qui ont été modifiés mais pas encore par d'autres transactions.
Aucune autre transaction ne peut modifier les données qui a été lu par le transaction en cours jusqu'à ce que le courant finalise la transaction.
D'autres transactions ne peut pas insérer de nouvelles lignes avec des valeurs clés entreraient dans la gamme de clés lecture par des déclarations contenues dans le courant transaction jusqu'à ce que le courant finalise la transaction.
serrures Range sont placés dans la gamme des valeurs clés qui correspondent à la conditions de recherche de chaque déclaration exécutée dans une transaction. cela bloque d'autres opérations de mise à jour ou l'insertion des lignes qui serait admissible pour l'une des déclarations exécutées par la transaction en cours. Ça signifie que si l'une des déclarations dans un transaction sont exécutées une seconde temps, ils liront le même ensemble de Lignes. Les verrous de gamme sont maintenus jusqu'à la transaction terminée. C'est le la plus restrictive de l'isolement les niveaux car il verrouille les gammes entières des clés et maintient les verrous jusqu'à ce que finalise de transaction. Car est inférieure concurrency, utilisez cette option seulement si nécessaire. Cette option a le même effet que la mise en HOLDLOCK sur toutes les tables de toutes les instructions SELECT dans une transaction.
Le principal problème avec ce niveau d'isolation des transactions est que c'est une jolie charge lourde sur le serveur, et sérialisés (comme son nom l'indique) tout accès, donc les performances de votre serveur et l'évolutivité souffriront, par exemple avec un très grand nombre d'utilisateurs, vous éventuellement obtenir beaucoup de délais d'attente pour les utilisateurs en attente d'une transaction à la fin.
Donc, en utilisant l'approche plus légère d'un identifiant de message global que INT IDENTITY
est certainement beaucoup mieux!