Database
 sql >> Teknologi Basis Data >  >> RDS >> Database

Mitos bahwa DROP dan TRUNCATE TABLE adalah Non-Logged

Ada mitos yang terus-menerus di dunia SQL Server bahwa DROP TABLE dan TRUNCATE TABLE perintah tidak dicatat.

Mereka tidak. Keduanya dicatat sepenuhnya, tetapi dicatat secara efisien.

Anda dapat dengan mudah membuktikan ini kepada diri sendiri. Jalankan kode berikut untuk menyiapkan database dan tabel pengujian, dan tunjukkan bahwa kita memiliki 10.000 baris di tabel kita:

CREATE DATABASE [TruncateTest];
GO
 
ALTER DATABASE [TruncateTest] SET RECOVERY SIMPLE;
GO
 
USE [TruncateTest];
GO
 
CREATE TABLE [TestTable] (
    [c1]    INT IDENTITY,
    [c2]    CHAR (8000) DEFAULT 'a');
GO
 
SET NOCOUNT ON;
GO
 
INSERT INTO [TestTable] DEFAULT VALUES;
GO 10000
 
SELECT
    COUNT (*) AS N'RowCount'
FROM
    [TestTable];
GO

Hasil:

Jumlah Baris
———–
10000

Dan kemudian kode berikut, yang memotong tabel dalam transaksi dan memeriksa jumlah baris:

BEGIN TRAN;
GO
TRUNCATE TABLE [TestTable];
GO
 
SELECT
    COUNT (*) AS N'RowCount'
FROM
    [TestTable];
GO

Hasil:

Jumlah Baris
———–
0

Sekarang meja itu kosong. Tapi saya bisa memutar kembali transaksi dan mengembalikan semua data lagi:

ROLLBACK TRAN;
GO
 
SELECT
    COUNT (*) AS N'RowCount'
FROM
    [TestTable];
GO

Hasil:

Jumlah Baris
———–
10000

Jelas TRUNCATE operasi harus dicatat jika tidak operasi roll back tidak akan bekerja.

Jadi dari mana kesalahpahaman itu berasal?

Itu berasal dari perilaku DROP dan TRUNCATE operasi di meja besar. Mereka akan menyelesaikan hampir secara instan, dan jika Anda melihat log transaksi menggunakan fn_dblog tepat setelah itu, Anda hanya akan melihat sejumlah kecil catatan log yang dihasilkan dari operasi tersebut. Angka kecil itu tidak berkorelasi dengan ukuran tabel yang terpotong atau dijatuhkan, sehingga seolah-olah DROP dan TRUNCATE operasi tidak dicatat.

Tapi mereka sepenuhnya login, seperti yang saya tunjukkan di atas. Jadi di mana catatan log untuk operasi?

Jawabannya adalah bahwa catatan log akan dibuat, hanya tidak segera, dengan mekanisme yang disebut 'penurunan yang ditangguhkan', yang ditambahkan di SQL Server 2000 SP3.

Ketika sebuah tabel dijatuhkan atau dipotong, semua halaman file data yang dialokasikan untuk tabel tersebut harus tidak dialokasikan. Mekanisme untuk ini sebelum SQL Server 2000 SP3 adalah sebagai berikut:

Untuk setiap tingkat yang dialokasikan ke tabel

Mulai

Dapatkan kunci alokasi eksklusif pada tingkat



Selidiki kunci halaman untuk setiap halaman sejauh (dapatkan kunci dalam mode eksklusif, dan segera jatuhkan, pastikan tidak ada orang lain yang mengunci halaman)



JANGAN lepaskan kunci tingkat, menjamin bahwa tidak ada orang lain yang dapat menggunakan tingkat itu



Pindah ke tingkat berikutnya

End

Karena semua penguncian dipertahankan hingga akhir operasi, dan setiap penguncian membutuhkan sedikit memori, manajer penguncian mungkin kehabisan memori saat DROP atau TRUNCATE dari meja yang sangat besar terjadi. Beberapa pelanggan SQL Server mulai menemukan bahwa mereka mengalami kondisi kehabisan memori pada SQL Server 2000, karena tabel tumbuh sangat besar dan jauh melampaui pertumbuhan memori sistem.

Mekanisme deferred-drop mensimulasikan DROP atau TRUNCATE operasi selesai dengan segera, dengan melepaskan pengait alokasi untuk tabel dan menempatkannya pada 'antrean penangguhan-jatuhkan', untuk kemudian diproses oleh tugas latar belakang. Operasi unhook-and-transfer ini hanya menghasilkan beberapa catatan log. Ini adalah operasi yang sedang dilakukan dan dibatalkan dalam contoh kode saya di atas.
'Tugas latar belakang yang ditangguhkan' berputar setiap beberapa detik dan membatalkan alokasi semua halaman dan perluasan pada antrian penangguhan-jatuhkan dalam jumlah kecil batch, menjamin bahwa operasi tidak akan kehabisan memori. Dealokasi ini semuanya dicatat sepenuhnya, tetapi ingat bahwa membatalkan alokasi halaman yang penuh dengan data atau catatan indeks tidak mencatat penghapusan individual dari catatan tersebut; alih-alih seluruh halaman hanya ditandai sebagai tidak dialokasikan dalam peta byte alokasi PFS (Page Free Space) yang relevan.

Dari SQL Server 2000 SP3 dan seterusnya, saat Anda melakukan DROP atau TRUNCATE tabel, Anda hanya akan melihat beberapa catatan log yang dihasilkan. Jika Anda menunggu sekitar satu menit, dan kemudian melihat log transaksi lagi, Anda akan melihat ribuan catatan log telah dihasilkan oleh operasi penangguhan-jatuhkan, masing-masing membatalkan alokasi halaman atau batas. Operasi dicatat sepenuhnya dan efisien.

Berikut ini contohnya, menggunakan skenario yang kami buat di atas:

CHECKPOINT;
GO
TRUNCATE TABLE [TestTable];
GO
SELECT
    COUNT (*) AS N'LogRecCount'
FROM
    fn_dblog (NULL, NULL);
GO

Hasil:

LogRecCount

———–

25

Seperti yang Anda lihat, jelas tidak ada catatan log yang membatalkan alokasi 10.000 halaman, ditambah 1.250 luasan di tabel TestTable.

Jika saya menunggu beberapa detik, lalu jalankan fn_dblog kode lagi, saya mendapatkan:

LogRecCount

———–

3811

Anda mungkin bertanya-tanya mengapa tidak ada setidaknya 10.000 catatan log – satu untuk setiap halaman yang dibatalkan alokasinya. Itu karena dealokasi halaman bahkan dicatat secara efisien – dengan satu catatan log yang mencerminkan perubahan alokasi halaman PFS untuk 8 halaman file data berturut-turut, alih-alih satu catatan log untuk setiap halaman file data yang mencerminkan perubahan status alokasinya di halaman PFS.

SQL Server selalu mencoba untuk menghasilkan log transaksi sesedikit mungkin, sambil tetap mengikuti aturan tentang logging penuh atau minimal berdasarkan model pemulihan saat ini. Jika Anda ingin melihat catatan log aktual yang dihasilkan oleh mekanisme unhook-and-transfer dan deferred-drop, cukup ganti * untuk COUNT (*) dalam kode fn_dblog di atas dan cari transaksi dengan Nama Transaksi yang disetel ke DeferredAllocUnitDrop::Process .

Di postingan mendatang, saya akan membahas internal yang mendukung mitos persisten lainnya seputar aspek kinerja SQL Server Storage Engine.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Memeriksa apakah kolom non-LOB perlu diperbarui

  2. Desain Bill of Material (BOM) yang Fleksibel dan Dapat Dikelola

  3. SQL UPDATE :Pelajari Cara Memperbarui Nilai Dalam Tabel

  4. Masalah Performa:Pertemuan Pertama

  5. Apa itu Injeksi SQL?