Sertোকানোর সময় ডিস্ক স্পেস পূর্ণ, কী ঘটে?


17

আজ আমি হার্ডড্রাইভ আবিষ্কার করেছি যা আমার ডাটাবেসগুলিতে পূর্ণ ছিল। এটি আগেও ঘটেছে, সাধারণত কারণটি বেশ স্পষ্ট। সাধারণত একটি খারাপ জিজ্ঞাসা থাকে, যার ফলে টেম্পডিবিতে প্রচুর পরিমাণে ছড়িয়ে পড়ে যা ডিস্ক পূর্ণ না হওয়া অবধি বৃদ্ধি পায়। এবার যা ঘটেছে তা একটু কমই স্পষ্ট হয়েছিল, কারণ টেম্পডিবি সম্পূর্ণ ড্রাইভের কারণ নয়, এটি ছিল ডাটাবেস নিজেই।

ঘটনা:

  • সাধারণ ডাটাবেসের আকার প্রায় 55 গিগাবাইট, এটি বেড়েছে 605 জিবি।
  • লগ ফাইলের আকার সাধারণ থাকে, ডেটা ফাইল বিশাল।
  • ডেটাফাইলে 85% উপলভ্য স্থান রয়েছে (আমি এটি 'বায়ু' হিসাবে ব্যাখ্যা করি: যে স্থানটি ব্যবহৃত হয়েছিল, তবে তা ছেড়ে দেওয়া হয়েছে S এসকিউএল সার্ভার একবার বরাদ্দকালে সমস্ত স্থান সংরক্ষণ করে)।
  • টেম্পডিবির আকার স্বাভাবিক।

আমি সম্ভবত কারণ খুঁজে পেয়েছি; একটি ক্যোয়ারী রয়েছে যা অনেক বেশি সারি নির্বাচন করে (খারাপ যোগদানের কারণে 11 বিলিয়ন সারি নির্বাচন হয় যেখানে কয়েক লক্ষ আশা করা যায়)। এটি এমন একটি SELECT INTOক্যোয়ারী, যা আমাকে অবাক করে দিয়েছিল যে নিম্নলিখিত পরিস্থিতিটি ঘটতে পারে কিনা:

  • নির্বাচন করুন কার্যকর করা হয়
  • লক্ষ্য সারণী তৈরি করা হয়
  • এটি নির্বাচন করা হিসাবে ডেটা .োকানো হয়
  • ডিস্কটি পূরণ করে, সন্নিবেশটিকে ব্যর্থ করে তোলে
  • নির্বাচন নির্বাচন বাতিল এবং ফিরে ঘূর্ণিত হয়
  • রোলব্যাক স্থান মুক্ত করে (ইতিমধ্যে সন্নিবেশিত ডেটা সরানো হয়েছে), তবে এসকিউএল সার্ভার খালি স্থান ছেড়ে দেয় না।

এই পরিস্থিতিতে, তবে, আমি তৈরির টেবিলটি SELECT INTOএখনও বিদ্যমান থাকার আশা করিনি , এটি রোলব্যাকের মাধ্যমে ফেলে দেওয়া উচিত। আমি এটি পরীক্ষা করেছি:

BEGIN TRANSACTION 
SELECT  T.x
INTO    TMP.test
FROM    (VALUES(1))T(x)

ROLLBACK

SELECT  * 
FROM    TMP.test

এর ফলে:

(1 row affected)
Msg 208, Level 16, State 1, Line 8
Invalid object name 'TMP.test'.

তবুও লক্ষ্য সারণী বিদ্যমান। প্রকৃত ক্যোয়ারী একটি সুস্পষ্ট লেনদেনের মধ্যে কার্যকর করা হয়নি যদিও এটি লক্ষ্য সারণির অস্তিত্বকে ব্যাখ্যা করতে পারে?

আমি যে অনুমানগুলি এখানে স্কেচ করেছি তা কি সঠিক? এটি সম্ভবত ঘটতে পারে?

উত্তর:


17

প্রকৃত ক্যোয়ারী একটি সুস্পষ্ট লেনদেনের মধ্যে কার্যকর করা হয়নি যদিও এটি লক্ষ্য সারণির অস্তিত্বকে ব্যাখ্যা করতে পারে?

হ্যাঁ, ঠিক তাই

আপনি যদি কোনওটির select intoবাইরে কোনও সাধারণ কাজ করেন explicit transaction, সেখানে transactionsঅটোোকমিট মোডে দুটি থাকে: প্রথমটি তৈরি করে tableএবং দ্বিতীয়টি এটি পূরণ করে।

আপনি নিজের কাছে এটি প্রমাণ করতে পারেন:

databaseএকটি পরীক্ষার সার্ভারে উত্সর্গীকৃত simple recovery model, প্রথমে একটি তৈরি করুন checkpointএবং নিশ্চিত করুন যে লগ সম্পর্কিত কয়েকটি সারি রয়েছে (2016 এর ক্ষেত্রে 3) checkpoint। তারপরে একটি select intoসারিতে একটি চালনা করুন এবং এর সাথে সম্পর্কিত logসন্ধানে আবার পরীক্ষা করুন :begin transelect into

checkpoint;

select *
from sys.fn_dblog(null, null);

select 'a' as col
into dbo.t3;  

select *
from sys.fn_dblog(null, null)
where Operation = 'LOP_BEGIN_XACT'
      and [Transaction Name] = 'SELECT INTO';

আপনার কাছে 2 টি সারি দেখিয়ে 2 টি সারি পাবেন transactions

আমি যে অনুমানগুলি এখানে স্কেচ করেছি তা কি সঠিক? এটি সম্ভবত ঘটতে পারে?

হ্যাঁ, তারা সঠিক।

এর insertঅংশটি select intoছিল rolled back, তবে এটি কোনও ডেটা স্পেস প্রকাশ করে না। আপনি এটি কার্যকর করে যাচাই করতে পারেন sp_spaceused; আপনি প্রচুর দেখতে পাবেন unallocated space

আপনি যদি ডাটাবেসটিকে এই অবৈধ স্থানটি ছেড়ে দিতে চান তবে shrinkআপনার ডেটা ফাইল করা উচিত ।


15

আপনি সঠিক, SELECT...INTOআদেশটি পারমাণবিক নয়। মূল পোস্টের সময় এটি নথিভুক্ত করা হয়নি, তবে এখন এমএস ডক্সের (ইয়ে ওপেন সোর্স!) পৃষ্ঠায় বিশেষভাবে নির্বাচন করুন - INTO ক্লজ (ট্রানজেক্ট-এসকিউএল) পৃষ্ঠায় ডাকা হয়েছে :

SELECT...INTOবিবৃতি দুটি অংশে পরিচালনা - নতুন টেবিল তৈরি করা হয়, এবং তারপর সারি প্রবেশ করানো হয়। এর অর্থ হ'ল যদি সন্নিবেশগুলি ব্যর্থ হয় তবে সেগুলি সমস্তই আবার ঘুরিয়ে দেওয়া হবে, তবে নতুন (খালি) সারণীটি থেকে যাবে। আপনার সফল বা সামগ্রিকভাবে ব্যর্থ হওয়ার জন্য যদি পুরো অপারেশনটির প্রয়োজন হয় তবে একটি স্পষ্ট লেনদেন ব্যবহার করুন ।

আমি একটি ডাটাবেস তৈরি করব যা সম্পূর্ণ পুনরুদ্ধারের মডেল ব্যবহার করে uses আমি এটিকে মোটামুটি ছোট লগ ফাইল দেব এবং তারপরে এটি বলব যে লগ ফাইলটি অটোগ্রোগ করতে পারে না:

CREATE DATABASE [SelectIntoTestDB]
ON PRIMARY 
( 
    NAME = N'SelectIntoTestDB', 
    FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL14.SQL2017\MSSQL\DATA\SelectIntoTestDB.mdf', 
    SIZE = 8192KB, 
    FILEGROWTH = 65536KB
)
LOG ON 
( 
    NAME = N'SelectIntoTestDB_log', 
    FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL14.SQL2017\MSSQL\DATA\SelectIntoTestDB_log.ldf', 
    SIZE = 8192KB, 
    FILEGROWTH = 0
)

এবং তারপরে আমি স্ট্যাকওভারফ্লো 2010 ডাটাবেসের আমার অনুলিপি থেকে সমস্ত পোস্ট সন্নিবেশ করার চেষ্টা করব। এটি লগ ফাইলে একটি গুচ্ছ স্টাফ লিখতে হবে।

USE [SelectIntoTestDB];
GO

SELECT *
INTO dbo.Posts
FROM StackOverflow2010.dbo.Posts;

এটি 4 সেকেন্ড চালানোর পরে নিম্নলিখিত ত্রুটির ফলস্বরূপ:

এমএসজি 9002, স্তর 17, রাজ্য 4, লাইন 1
ডাটাবেস 'সিলেক্ট ইন্টেস্টেডিবি' এর জন্য লেনদেনের লগ 'ACTIVE_TRANSACTION' এর কারণে পূর্ণ।

তবে আমার নতুন ডাটাবেসে একটি খালি পোস্টের টেবিল রয়েছে:

নতুন নির্মিত টেবিল থেকে শূন্য ফলাফলের স্ক্রিনশট

সুতরাং, আপনি যেমন সন্দেহ করেছিলেন তেমন CREATE TABLEসফল, তবে INSERTঅংশটি সবই আবার ঘুরিয়ে দেওয়া হয়েছিল। একটি কার্যপ্রণালী হ'ল একটি স্পষ্ট লেনদেন (যা আপনি ইতিমধ্যে আপনার প্রশ্নে উল্লেখ করেছেন) ব্যবহার করবেন।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.