Penegasan SQL Server SQL 2016: File: <pageref.cpp>, line = 951 Gagal Penegasan

8

Saya saat ini meningkatkan gudang data kami dari SQL 2012 ke SQL 2016. Saya memiliki DW lama dan baru saya yang berjalan berdampingan secara paralel.

Proses ETL saya (Kerangka kerja yang dikembangkan dalam SSIS oleh pihak ke-3) telah berjalan dengan sukses selama lebih dari 2 tahun pada 2012 tetapi gagal pada 2016. Sejauh ini database dan proses ETL identik.

Kedua Server adalah mesin Virtual yang berjalan di VMWare. Old Server is Win 2008 dengan RAM 24Gb. SQL 2012 Std. Maks mem atur ke 16Gb. Server Baru adalah Win 2012 dengan 64Gb RAM. SQL 2016 dev. Maks mem atur ke 50Gb. DW baru menjalankan v13.0.1601.5 Edisi Pengembang RTM (64-bit).

Saat menjalankan proses ETL saya langkah-langkah memuat yang menggunakan SQL Merge ke dalam tabel dimensi atau fakta gagal dengan kesalahan berikut.

Teks lengkap:

KETERANGAN: Pernyataan SQL Server: File:, line = 951 Pernyataan Gagal = 'IS_OFF (BUF_MINLOGGED, m_buf-> bstat) || pageModifyType! = PageModifyType_Contents || GetPagePtr () -> IsTextPage () '. Kesalahan ini mungkin terkait waktu. Jika kesalahan tetap terjadi setelah menjalankan kembali pernyataan, gunakan DBCC CHECKDB untuk memeriksa database untuk integritas struktural, atau restart server untuk memastikan struktur data dalam memori tidak rusak.

Seperti yang disarankan, saya telah menjalankan DBCC dan tidak ada kesalahan yang ditemukan. Saya juga me-restart SQL. Saya kemudian memulai kembali proses ETL dan mendapatkan kesalahan yang sama.

Pencarian saya untuk kesalahan ini menunjukkan kesalahan yang dikenal di SQL 2008, 2012 & 2014 dan diperbaiki dalam pembaruan terbaru & kumulatif pembaruan berikutnya. jadi saya agak terkejut melihatnya muncul kembali pada tahun 2016.

Tautan yang saya temukan mengatakan itu memengaruhi SSIS ketika mencoba melakukan penyisipan jika basis data dalam model pemulihan Sederhana atau Massal Tercatat. (Saya menjalankan model pemulihan sederhana)

Solusi yang disarankan adalah mengubah model pemulihan Db ke FULL. Saya telah mencoba ini dan berhasil, tetapi tidak banyak solusi untuk Gudang Data.

Adakah orang lain yang mengalami hal ini pada tahun 2016?

Adakah yang bisa menyarankan solusi alternatif?

Pembaruan:

26/7/2016: Saya menerapkan Pembaruan Kritis KB3164398 (v13.0.1708.0) dan masalahnya masih ada.

27/7/2016: Saya telah menerapkan Pembaruan Kumulatif CU1 KB3164674 (v13.0.2149.0).

3/8/2016: Kesalahan terjadi semalam di kubus terkecil kami. CU1 tidak memperbaiki masalah. Hari ini saya melaporkan bug di MS Connect dan saya juga mencatat panggilan dukungan dengan Microsoft.

12/8/2016: Dukungan MS merespons pada awalnya, tetapi jawabannya adalah "Kami tidak memiliki perbaikan untuk itu". Cowok Pendukung akan mendiskusikannya dengan rekan-rekannya dan kembali kepada saya. 8 hari kemudian saya belum mendengar kabar darinya.

Meskipun saya tidak memiliki 'perbaikan', kami menemukan solusi yang cocok untuk kami. Lihat jawaban saya yang diposting.

29/9/2016. Saya menerapkan CU2 minggu lalu. Pada hari Kamis kami secara tidak sengaja menjalankan versi lama penggabungan yang gagal lagi dengan kesalahan yang sama. Jadi .. CU2 belum memperbaikinya juga.

23/1/2017 : Saya Menerapkan 2016 SP1 CU1 dan saya yakin ini telah menyelesaikan masalah. Khususnya KB3205964

Pak Bersumpah banyak
sumber

Jawaban:

2

Melihat KB Anda memiliki beberapa opsi / solusi:

  1. Beralih ke model pemulihan LENGKAP. Anda mengatakan "ini tidak banyak pilihan untuk gudang" tapi itu benar-benar hanya masalah menyiapkan cadangan log transaksi secara teratur misalnya 15 menit dan kemudian membuangnya. SSIS / Rencana Perawatan memiliki tugas stok untuk melakukan ini . Anda akan kehilangan transaksi dalam jumlah besar, tetapi saya tidak pernah menemukan ini membuat perbedaan besar dalam runtime, hanya ukuran log. Anda bahkan dapat membuat cadangan log ke nomor yang tidak akan saya jelaskan di sini. Jika Anda tidak yakin apa yang harus dilakukan, tanyakan DBA setempat. Ruang disk dan retensi cadangan log transaksi lebih mudah untuk diselesaikan daripada kesalahan fatal. Ketika masalah ini akhirnya diselesaikan, Anda dapat beralih kembali.
  2. KB menyebutkan "beberapa pernyataan BULK INSERT dalam satu transaksi yang didistribusikan". Tidak jelas dari pertanyaan Anda bagaimana sisipan massal Anda diatur. Apakah Anda menggunakan SSIS untuk menjalankan tugas 'Jalankan SQL' yang menggunakanMERGEperintah? Apa yang dimaksud dengan 'BULK INSERT' di sini? Apakah ada cara untuk mengubah pendekatan Anda menjadi BULK INSERT tunggal, satu per satu misalnya? Dalam SSIS Anda dapat mengatur 'MaxConcurrentExecutables' menjadi 1 untuk sementara misalnya, lihat apakah itu membantu. Ikatkan ke variabel konfigurasi sehingga Anda dapat mengubahnya kembali nanti. Jelas itu akan memperlambat segalanya tetapi Anda lebih memilih ETL Anda untuk menyelesaikan daripada gagal dengan cepat. Melakukan hal-hal secara paralel adalah pola yang baik dan kekuatan SSIS yang nyata, tetapi Anda hanya bisa bergerak secepat komponen paling lambat Anda; katakanlah Anda memiliki 10 dimensi yang membutuhkan waktu satu menit dan satu fakta yang membutuhkan waktu satu jam, ETL Anda selesai dalam satu jam berjalan paralel atau 1 jam 10 menit berjalan secara seri.
  3. MERGEbagus tetapi memang memiliki beberapa masalah. Anda dapat mempertimbangkan mengonversi kembali ke INSERT/ UPDATE. Anda juga harus menggunakan HOLDLOCKdengan MERGEsesuai di sini . Apakah Anda menggunakan petunjuk itu? Apakah ada bedanya dengan masalah ini jika Anda melakukannya? Kami memiliki masalah di awal SQL 2014 membangun di mana menggunakan MERGEdengan DML OUTPUTkomposit ( klausul) ke dalam kolom menyebabkan pernyataan semacam ini - saya membuat mereka mengambil indeks kolom toko dari dimensi, yang mereka tambahkan tanpa memberi tahu saya.
  4. Jenis penanganan transaksi apa yang Anda lakukan? Terkadang dengan ETL posisi dapat diulang dengan hanya menjalankan kembali. Terkadang Anda membutuhkannya untuk gagal dan kembalikan. Bagaimana Anda menerapkan ini? Dapat diubah jadi itu bukan "transaksi terdistribusi tunggal"?

Semoga berhasil.

wBob
sumber
Hai @ wBob terima kasih atas balasan Anda. Untuk menjawab pertanyaan Anda. 1. Kita berbicara tentang mengekstraksi tabel 20-30Gb dalam satu langkah. memindahkan lebih dari 100Gb data. Saya khawatir tentang membuang log TX dan juga penyimpanannya. Mungkin saya bisa membuat cadangan log langkah dalam ETL setelah setiap ekstrak? 2. Ya SSIS memanggil tugas SQL untuk melakukan penggabungan. Setiap langkah dieksekusi secara berurutan. Pada saat penggabungan berjalan, itu satu-satunya tugas yang dijalankan. 3. Alat ETL kami adalah kerangka kerja yang disediakan oleh vendor. Begini Cara kerjanya. Tidak yakin tentang petunjuk. akan mengecek. 4. Tidak ada penanganan TX. SQL lurus.
Sir Swears-a-lot
Jadi jika proses yang berhasil tidak berlanjut, coba t-log 100GB dengan cadangan log setelah setiap tabel dipindahkan, itu akan mengurutkannya. Jelas Anda harus menguji. Adakah fitur lain yang harus kita ketahui tentang target? Kolom, partisi, pengindeksan berlebihan?
wBob
Saat ini tidak ada fitur yang belum ada di DW kami pada 2012 std. DW / Datamarts baru adalah salinan asli dokumen asli, Tidak ada kolom toko atau partisi. Indeks minimal (tetapi efektif). Kami saat ini fokus pada langkah platform seperti untuk suka. Pada akhirnya DW baru kami akan menjadi 2016 Perusahaan. Tapi kami tidak menambahkan fitur tingkat Perusahaan sampai kami memiliki dasar-dasar yang berfungsi.
Sir Swears-a-lot
Hai @ wBob. Kami telah mengimplementasikan saran Anda dengan memecah insert dari penggabungan. Tetapi mengingat cara saya mengajukan pertanyaan, saya tidak yakin apa yang memenuhi syarat sebagai jawaban yang benar. tapi saya pikir Anda telah membawa saya ke solusi yang valid dan bisa diterapkan.
Sir Swears-a-lot
2

Saya percaya ini telah diselesaikan pada 2016 SP1 CU1.

Khususnya oleh KB3205964

Pak Bersumpah banyak
sumber
1

Ini diperbaiki dengan menerapkan pembaruan kumulatif 1 (CU1) untuk MSSQL2016 lihat tautan https://support.microsoft.com/en-us/kb/3164674

Steve Neshausen
sumber
Steve bekerja dengan saya dalam hal ini. kami pikir kami sudah menyelesaikannya tetapi tidak ada cerutu. jadi saya sudah menghapus kredit dan downvoted.
Sir Swears-a-lot
1

Saya yakin kami telah menemukan solusi lain. Saya memposting jawaban saya karena saya pikir ini mungkin berguna, dan itu cukup berbeda dari saran wBob.

Kami telah mengubah bagian sisipan dari pernyataan gabungan sehingga memasukkan ke tabel temp daripada target aslinya.

Setelah pernyataan gabungan dieksekusi, kami kemudian memasukkan dari tabel # ke dalam target.

Ini tidak ideal, tetapi setidaknya penggabungan masih menangani kompleksitas 'upert' dengan menandai baris yang telah pensiun / kedaluwarsa.

Kami menemukan ini sebagai trade-off yang dapat diterima dibandingkan dengan sepenuhnya menulis ulang penggabungan sebagai sisipan dan pembaruan yang terpisah.

CREATE TABLE #Activity(
[ETL_ActivitySurrogateKey] [int] IDENTITY(1,1) NOT NULL,
[Field1] [varchar](255) NULL,
)

-- Insert statements for procedure here
INSERT INTO #Activity ( [Field1],2,3,etc )

SELECT [Field1],2,3,etc
FROM 
(
    MERGE [DDS_OZ_CC].[dimActivity] AS target 
    USING (
      SELECT [Field1],2,3,etc
      FROM [STAGE_OZ_CC].[Transform_Activity]
      ) as source
    ON
    (
      target.RowIsCurrent = source.RowIsCurrent
         AND target.[Field1] = source.[Field1]
    )
    WHEN MATCHED 
        AND (        
        EXISTS (SELECT target.Level5Id EXCEPT SELECT source.Level5Id)
    )
    THEN
      UPDATE SET 
        ETL_ValidToDateTime = source.ETL_ValidFromDateTime 
       ,ETL_RowIsCurrent = 0 
       ,ETL_LastTouchedBy = source.ETL_LastTouchedBy 
       ,ETL_RowChangeReason = 'SCD2 Retired' 

    WHEN NOT MATCHED THEN 
    INSERT 
    (    
     [Field1],2,3,etc
    )
    VALUES (      
      source.[Field1],2,3,etc
    )
       WHEN NOT MATCHED BY SOURCE AND target.ETL_RowIsCurrent = 1
       THEN UPDATE SET
       ETL_RowIsCurrent = 0 
       ,ETL_RowChangeReason = 'Fact Removed' 
       ,ETL_LastTouchedBy = 'Unknown'

  OUTPUT
    $action      
      ,source.[Field1],2,3,etc    

  ) AS MergeOutput
  (
    action  
    ,[Field1],2,3,etc   
  ) 

  WHERE ACTION = 'UPDATE' AND ETL_RowIsCurrent = 1

    INSERT INTO [DDS_OZ_CC].[dimActivity]
    ( [Field1],2,3,etc  )
    SELECT [Field1],2,3,etc
    FROM #Activity

    END
Pak Bersumpah banyak
sumber
Ok terima kasih Peter. Hanya karena ketertarikan, apakah Anda mencoba petunjuk HOLDLOCK?
wBob
Tidak, saya tidak. Setelah membaca artikel Aaron Bertrands tentang hal itu, pemahaman saya adalah benar-benar tentang masalah konkurensi dengan banyak pengguna. Dalam kasus kami, proses ETL adalah satu-satunya yang menjalankan.
Sir Swears-a-lot
Saya pikir itu layak untuk dicoba hanya untuk melihat apakah Anda mendapatkan perilaku yang berbeda, plus itu mungkin praktik terbaik, hanya untuk mengatakan Anda tidak berbarengan sekarang tidak berarti Anda mungkin tidak berada di masa depan. Bagaimanapun, dilakukan dengan baik untuk menemukan solusi dan ke masalah berikutnya
:)
Saya ingin, tetapi sayangnya kita berada di bawah batasan waktu. Setelah kami menemukan solusi yang bisa diterapkan, bos membuat panggilan untuk melanjutkan.
Sir Swears-a-lot