Dari sudut pandang saya, server Anda memiliki masalah kinerja yang serius. Bahkan jika kita berasumsi bahwa tidak ada catatan dalam kueri
select some_col with (nolock) where id_col between 57000000 and 57001000
ada di memori, tidak perlu 21 detik untuk membaca beberapa halaman secara berurutan dari disk (indeks berkerumun Anda di id_col tidak boleh terfragmentasi jika itu adalah identitas otomatis dan Anda tidak melakukan sesuatu yang bodoh seperti menambahkan "desc" ke definisi indeks).
Tetapi jika Anda tidak dapat/tidak akan memperbaikinya, saran saya adalah membuat pembaruan dalam paket kecil seperti 100-1000 catatan sekaligus (tergantung pada berapa banyak waktu yang digunakan fungsi pencarian). Satu pembaruan/transaksi tidak boleh lebih dari 30 detik.
Anda melihat setiap pembaruan menyimpan kunci eksklusif pada semua catatan yang dimodifikasi hingga transaksi selesai. Jika Anda tidak menggunakan transaksi eksplisit, setiap pernyataan dieksekusi dalam satu konteks transaksi otomatis, sehingga kunci dilepaskan saat pernyataan pembaruan selesai.
Tetapi Anda masih bisa mengalami kebuntuan seperti itu, tergantung pada apa yang dilakukan proses lain. Jika mereka juga memodifikasi lebih dari satu record pada satu waktu, atau bahkan jika mereka mengumpulkan dan menahan kunci baca pada beberapa baris, Anda bisa mendapatkan kebuntuan.
Untuk menghindari kebuntuan, pernyataan pembaruan Anda perlu mengunci semua catatan yang akan diubahnya sekaligus. Cara melakukannya adalah dengan menempatkan pernyataan pembaruan tunggal (dengan hanya beberapa baris yang dibatasi oleh id_col) dalam transaksi serial seperti
IF @@TRANCOUNT > 0
-- Error: You are in a transaction context already
SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
-- Insert Loop here to work "x" through the id range
BEGIN TRANSACTION
UPDATE SOMETABLE
SET [some_col] = dbo.ufn_SomeFunction(CONVERT(NVARCHAR(500), another_column))
WHERE [some_col] = 243 AND id_col BETWEEN x AND x+500 -- or whatever keeps the update in the small timerange
COMMIT
-- Next loop
-- Get all new records while you where running the loop. If these are too many you may have to paginate this also:
BEGIN TRANSACTION
UPDATE SOMETABLE
SET [some_col] = dbo.ufn_SomeFunction(CONVERT(NVARCHAR(500), another_column))
WHERE [some_col] = 243 AND id_col >= x
COMMIT
Untuk setiap pembaruan, ini akan mengambil pembaruan/kunci rentang kunci eksklusif pada catatan yang diberikan (tetapi hanya mereka, karena Anda membatasi pembaruan melalui kunci indeks berkerumun). Ini akan menunggu pembaruan lainnya pada catatan yang sama selesai, kemudian menguncinya (menyebabkan pemblokiran untuk semua transaksi lain, tetapi masih hanya untuk catatan yang diberikan), kemudian memperbarui catatan dan melepaskan kunci.
Pernyataan tambahan terakhir adalah penting, karena akan mengambil kunci rentang kunci hingga "tak terhingga" dan dengan demikian mencegah penyisipan yang merata di akhir rentang saat pernyataan pembaruan berjalan.