Je suis assez nouveau pour les serrures et les allusions.
J'ai une table avec de très fréquentes opérations SELECT
et INSERT
. La table contient 11 millions d’enregistrements.
J'ai ajouté une nouvelle colonne et j'ai besoin de copier les données d'une colonne existante de la même table dans la nouvelle colonne.
Je prévois d'utiliser l'indicateur ROWLOCK
pour éviter la remontée des verrous au niveau des tableaux et le blocage de toutes les autres opérations sur la table. Par exemple:
UPDATE
SomeTable WITH (ROWLOCK)
SET
NewColumn = OldColumn
Des questions:
NOLOCK
au lieu de ROWLOCK
? Remarque: une fois les enregistrements insérés dans la table, la valeur de OldColumn ne change pas. Par conséquent, NOLOCK
ne provoque pas de lectures modifiées.NOLOCK
a-t-il même un sens dans ce cas, car SQL Server devrait malgré tout obtenir des verrous de mise à jour pour UPDATE
.Je sais que les allusions sont à éviter et que SQL Server fait généralement des choix plus judicieux, mais je ne souhaite pas que la table soit verrouillée pendant cette mise à jour.
Essayez et mettez à jour en lots.
DECLARE @Batch INT = 1000
DECLARE @Rowcount INT = @Batch
WHILE @Rowcount > 0
BEGIN
;WITH CTE AS
(
SELECT TOP (@Batch) NewColumn,OldColumn
FROM SomeTable
WHERE NewColumn <> OldColumn
OR (NewColumn IS NULL AND OldColumn IS NOT NULL)
)
UPDATE cte
SET NewColumn = OldColumn;
SET @Rowcount = @@ROWCOUNT
END
J'ai adopté l'approche de @ pacreely (voir sa réponse à cette question) consistant à mettre à jour par lots et créé une variation update...top
. J'ai ajouté le conseil (rowlock) dire au serveur SQL de garder les verrous au niveau des lignes.
Voir update ... top pour plus de détails. Notez également que vous ne pouvez pas utiliser order by
lorsque vous utilisez top
dans une instruction update
, insert
, merge
, delete
afin que les lignes référencées ne soient organisées dans aucun ordre.
declare @BatchSize int = 1000
declare @RowCount int = @BatchSize
while @RowCount > 0
begin
update top (@BatchSize) SomeTable with (rowlock)
set NewColumn = OldColumn
where
NewColumn <> OldColumn or
(
NewColumn is null and
OldColumn is not null
)
select @RowCount = @@rowcount
end
Cette question a une réponse sur le site des administrateurs de base de données sur StackExchange ici: https://dba.stackexchange.com/questions/127158/how-to-get-sql-insert-and-or-update-to-not- lock-whole-table-on-ms-sql-server