มีการอัปเกรดแบบแทนที่ SQL Server แบบไม่ดีเหมือนที่เคยเป็นมาหรือไม่?


78

ฉันได้ทำงานกับเซิร์ฟเวอร์ SQL ในการเปิดและปิดตั้งแต่ SQL Server 6.5 คำแนะนำเก่าที่ยังคงดังในหัวของฉันก็ไม่เคยที่จะทำการอัพเกรดในสถานที่

ฉันกำลังอัปเกรดระบบ 2008 R2 DEV และ TEST เป็น SQL Server 2012 และต้องใช้ฮาร์ดแวร์เดียวกัน ความคิดที่ไม่จำเป็นต้องกู้คืนการกำหนดค่าบริการรายงานของฉันนั้นน่าสนใจมากและฉันก็ขัดกับเวลาที่ชาญฉลาดจริงๆ ไม่มีบริการวิเคราะห์ที่เกี่ยวข้องหรือสิ่งใดที่ผิดปกติหรือไม่เป็นมาตรฐาน - ติดตั้งเฉพาะเอ็นจิ้นฐานข้อมูลและบริการรายงานเท่านั้น

มีใครประสบปัญหาร้ายแรงกับการอัปเกรดแบบแทนที่หรือไม่ หรือฉันควรประเมินตำแหน่งของฉันเกี่ยวกับการอัปเกรดแบบแทนที่?


ฉันเลือกที่จะทำการอัปเกรดแบบ inplace บนเซิร์ฟเวอร์ 1 เครื่องที่มีการติดตั้งบริการรายงาน ปัญหาเดียวที่ฉันเจอคือการพยายามใช้เครื่องมือส่งออกนำเข้าใน SSMS กับไคลเอ็นต์ดั้งเดิม 11 การพยายามเปลี่ยนรูปล้มเหลวโดยมีข้อผิดพลาดเกี่ยวกับประเภทข้อมูลที่ไม่รู้จัก วิธีแก้ปัญหาที่ฉันใช้คือบันทึกแพคเกจและเรียกใช้ใน SQL Data Tools (การแทนที่ BIDS) ซึ่งทำงานได้ดี ฉันคิดว่าสิ่งนี้จะต้องทำอย่างไรกับไฟล์ปรับแต่งสำหรับ SSIS 2008 ที่ไม่ถูกเขียนทับ มันเกิดขึ้นกับฉันในภายหลังคุณอาจจะสามารถเปลี่ยนลูกค้าพื้นเมืองกลับไปเป็น 10 ได้
DamagedGoods

คำตอบ:


92

คำตอบสั้น ๆ จริง ๆ - ในสถานที่ก็โอเค คุณสามารถตรวจสอบการกำหนดค่าของคุณในภายหลังและใช้แนวทางปฏิบัติที่ดีที่สุดสำหรับ SQL Server 2012

คำตอบอีกต่อไปในการอัพเกรด / ย้ายเซิร์ฟเวอร์ SQL

ดังนั้นนี่คือสิ่งที่เป็นความเห็นและไม่มีคำตอบที่ไม่ถูกต้องหรือถูกต้อง แต่ฉันชอบการอัพเกรดรูปแบบการย้ายถิ่นมากกว่าเหตุผลหลายประการ ตามที่ได้กล่าวไว้ - ลูกค้าของฉันบางคนด้วยเหตุผลต่าง ๆ ไม่มีทางเลือกนอกจากทำในสถานที่จริง ๆ แล้วตั้งแต่ SQL Server 2005 การอัปเกรดแบบแทนที่ไม่ได้เลวร้ายอย่างที่เคยเป็น

ทำไมฉันถึงชอบการโยกย้ายไปยังการอัปเกรดแบบแทนที่

  • Easier Rollback - หากมีบางอย่างผิดปกติคุณสามารถย้อนกลับโดยพูดง่ายๆว่า "เรายกเลิกการอัพเกรดโปรดเปลี่ยนสตริงการเชื่อมต่อไปยังเซิร์ฟเวอร์เก่าในขณะที่เราแก้ไขปัญหานี้" ด้วยการติดตั้งแบบในสถานที่คุณกำลังแก้ไขมันหรือไม่ก็ตาม
  • Refresh Hardware - ฮาร์ดแวร์เปลี่ยนแปลงอย่างรวดเร็ว คุณสามารถติดกับฮาร์ดแวร์ที่เหมาะสมกับ บริษัท ของคุณเมื่อ 4 ปีก่อน แต่ไม่เหมาะกับวันนี้และอีกสี่ปีข้างหน้าด้วยการอัปเกรดแบบแทนที่ คุณอาจจะต้องทำการโยกย้ายในบางจุดต่อไปสำหรับฮาร์ดแวร์ใหม่
  • Feel Better - Sure ... อันนี้เป็นเรื่องส่วนตัว แต่รู้สึกดีที่รู้ว่าคุณกำลังเริ่มต้นด้วยการติดตั้งระบบปฏิบัติการใหม่การติดตั้ง SQL แบบใหม่ที่ไม่มีใยแมงมุมจากบุคคลในงานก่อนหน้าคุณ (หรือคุณก่อนที่คุณจะรู้ว่าคุณรู้อะไร วันนี้) ที่อาจทำให้คุณปวดหัวในอนาคต
  • ระบบปฏิบัติการใหม่ - การโยกย้ายเปิดโอกาสให้คุณเริ่มต้นด้วยระบบปฏิบัติการเวอร์ชันใหม่หากคุณไม่ได้อยู่ในระบบล่าสุดและยิ่งใหญ่ที่สุดในวันนี้
  • คุณสามารถทดสอบได้ - เคยต้องการรับชุดของเส้นเขตแดนบนเครื่องใหม่ก่อนที่คุณจะติดตั้ง SQL และทำให้มันคลาวด์กับฐานข้อมูลและการใช้งานหรือไม่? คุณสามารถทำได้ตอนนี้
  • บางครั้งการแอบดูแนวปฏิบัติที่ดีที่สุดง่ายกว่า - บัญชีบริการ SQL Server อาจเป็นผู้ดูแลระบบในเครื่อง บางทีผู้ดูแลระบบ Builtin อยู่ในบทบาทเซิร์ฟเวอร์ SA อาจมีบางสิ่งที่ถูกแฮ็กเข้าด้วยกันเพื่อให้ทำงานได้ก่อน คุณสามารถแก้ไขได้ทั้งหมดและเริ่มต้นใหม่
  • สภาพแวดล้อมการทดสอบฟรีและการนอนหลับเพิ่ม - มันเป็นประโยชน์อย่างมากที่จะมีสภาพแวดล้อมที่คุณสามารถทำงานได้ล่วงหน้าก่อนวันที่น่าสนใจเมื่อคุณทำให้สภาพแวดล้อมใหม่นี้มีชีวิต การย้ายข้อมูลไปยังสภาพแวดล้อมใหม่หมายความว่าคุณสามารถสร้างมันได้ในช่วงเวลาทำการก่อนหน้าวันที่ตัดจริงของคุณและทดสอบในหลาย ๆ ทางก่อนเวลา คุณสามารถรันการทดสอบการถดถอยแบบเต็มบนแอปพลิเคชันและระบบทั้งหมดเป็นเวลาหลายวันและมีความอุ่นใจอย่างยิ่งก่อนที่คุณจะทำการกู้คืน / เชื่อมต่อชุดสุดท้ายและตัดแอปพลิเคชันทั้งหมดและเข้าถึงสภาพแวดล้อมใหม่
  • คุณไม่ต้องทำทั้งหมดในคราวเดียวสถานการณ์ทั่วไปที่ฉันพบคือสภาพแวดล้อมที่พยายามรวมเข้ากับอินสแตนซ์เพียงไม่กี่สถานการณ์ อาจเป็นหนึ่งต่อรุ่นบางทีหนึ่งต่อ "ระดับ" และรุ่น โครงการเหล่านี้จำนวนมากมีระยะเวลาที่แตกต่างกันสำหรับแอปพลิเคชันและฐานข้อมูลต่าง ๆ โดยอิงจากการทดสอบแผนโครงการและการรับรองความตรงต่อเวลาของผู้ขาย การย้ายข้อมูลหมายความว่าคุณสามารถย้ายฐานข้อมูลที่พร้อมเมื่อพวกเขาพร้อมและยังจัดการคำขอสำหรับฐานข้อมูลเหล่านั้นที่ไม่สามารถย้ายด้วยเหตุผลใดก็ตาม

ใจคุณฉันไม่ได้บอกว่าคุณต้องทำสิ่งนี้ในฐานะการย้ายถิ่น In-Place ใช้งานได้และทำงานได้ดีหากคุณไม่ได้วางแผนที่จะซื้อฮาร์ดแวร์ใหม่ในงบประมาณของคุณและไม่สามารถทำได้สำหรับการอัพเกรดนี้ การสนับสนุนในกระบวนการอัปเกรดนั้นดีกว่ามากในช่วง 6.5 วันดังนั้นคุณจะไม่ทำให้ตัวเองอยู่ในสถานะที่ไม่ดีทำเช่นนี้

หากคุณวางแผนที่จะทำในสถานที่สำหรับ dev / test แต่ต้องการทำการโยกย้ายเพื่อการผลิตคุณอาจพิจารณาทำการโยกย้ายอย่างน้อยหนึ่งครั้งก่อนการผลิต วิธีนี้คุณสามารถจัดการรายการตรวจสอบล่วงหน้าและจัดการกับปัญหาที่อาจเกิดขึ้นที่คุณไม่ได้คิด

แนบ / แยกออกจากการสำรองข้อมูล / กู้คืนสำหรับการย้ายข้อมูล

หากคุณตัดสินใจที่จะใช้วิธีการโยกย้ายยังมีอีกหนึ่งการตัดสินใจที่คุณอาจยังคงมีการอภิปรายมากกว่าและนั่นคือวิธีที่คุณย้ายฐานข้อมูลของคุณไปยังสภาพแวดล้อมใหม่ คุณสามารถแยกฐานข้อมูลของคุณจากเซิร์ฟเวอร์เก่าและเชื่อมต่อกับใหม่หรือสำรองและเรียกคืนได้

ฉันต้องการสำรอง / กู้คืน ข้อได้เปรียบที่ใหญ่ที่สุดที่ฉันได้ยินเกี่ยวกับการถอด / เชื่อมต่อคือช่วยประหยัดเวลา สำหรับฉันการสำรองข้อมูล / คืนค่าชนะด้วยเหตุผลบางประการ

  • คงการเข้าถึงเก่าไว้ - สิ่งนี้ช่วยให้คุณยังคงมีฐานข้อมูลที่สามารถเข้าถึงได้บนเซิร์ฟเวอร์ต้นทาง แยก / แนบควรทำเช่นเดียวกัน แต่จะต้องมีขั้นตอนไม่กี่และมีห้องพักสำหรับข้อผิดพลาดของมนุษย์กับถอด / แนบที่อาจซับซ้อนนี้
  • คุณรับประกันว่าคุณมีการสำรองข้อมูล - แทนที่จะเพียงแค่นำฐานข้อมูลจากการแยกออกและอาจลืมขั้นตอนการสำรองข้อมูลคุณต้องแน่ใจว่าคุณได้ทำการสำรองข้อมูลแล้ว
  • ข้อผิดพลาดของมนุษย์ - หากคุณลบไฟล์ผิดลืมว่าคุณกำลังส่งอะไรหรือทำตามขั้นตอนของคุณคุณจะเสี่ยงมากโดยการย้ายข้อมูลและล็อกไฟล์ไปยังฐานข้อมูลของคุณ ตอนนี้คุณสามารถลดสิ่งนี้ได้โดยการคัดลอกแทนการตัด (และถ้าคุณแยกออกคุณควรออกไปจากนิสัยที่ถูกตัดและวาง) แต่คุณสามารถทำให้ยุ่งเหยิงได้ SQL Server ไม่ได้ล็อคไฟล์เหล่านั้นอีกต่อไปและมันง่ายเกินไปที่จะลบไฟล์โดยไม่ตั้งใจเพื่อให้ฉันเสี่ยง
  • มันไม่ใช่เรื่องที่ช้าลง - การสำรองข้อมูลและคัดลอกมันเป็นเวลาที่น้อยมาก แต่ก็ไม่ได้ว่ามากว่าผมเต็มใจที่จะจ่ายเพิ่มความเสี่ยงให้มัน ในความเป็นจริง - การใช้แบบจำลองการกู้คืนข้อมูลเต็มรูปแบบและการสำรองข้อมูลบันทึกคุณสามารถลดเวลาดาวน์ไทม์ให้ต่ำลงสำหรับ cutovers ตามที่อธิบายไว้ด้านล่างใน "วิธีการสร้างวิธีการโยกย้ายได้เร็วขึ้น"

หากคุณตัดสินใจที่จะทำการสำรองข้อมูล / กู้คืน - นั่นหมายความว่าฐานข้อมูลเก่าของคุณจะยังคงออนไลน์อยู่ ฉันต้องการทำให้ฐานข้อมูลนั้นออฟไลน์หลังจากทำการสำรองข้อมูล บางครั้งฉันก้าวไปอีกขั้นและทำให้อินสแตนซ์ SQL ทั้งหมดออฟไลน์หลังจากที่ฉันได้เขียนสคริปต์เกี่ยวกับความปลอดภัยงานเซิร์ฟเวอร์ที่เชื่อมโยงใบรับรองการตั้งค่าเมลฐานข้อมูลและข้อมูลอื่น ๆ ของอินสแตนซ์อื่น ๆ สิ่งนี้จะช่วยหลีกเลี่ยงปัญหาระหว่างการทดสอบที่มีคนพูดว่า "ทุกอย่างดูดี!" เพียงตระหนักวันหรือสองวันหลังจากนั้นพวกเขาได้พูดคุยกับฐานข้อมูลเก่าบนเซิร์ฟเวอร์เก่า การทำให้ฐานข้อมูลเหล่านั้นออฟไลน์หรือออฟไลน์ทั้งหมดช่วยให้คุณสามารถป้องกันผลบวกปลอมและความยุ่งเหยิงที่เกิดขึ้น

วิธีการทำให้การโยกย้ายเข้าใกล้เร็วขึ้น

คุณสามารถลดเวลาหยุดทำงานที่จำเป็นสำหรับ cutover จากสภาพแวดล้อมเก่าสู่สภาพแวดล้อมใหม่สำหรับสภาพแวดล้อมการผลิตที่มีงานไม่มากพร้อมเวลาหยุดทำงานเพียงเล็กน้อยโดยใช้แบบจำลองการกู้คืนเต็มรูปแบบ โดยทั่วไป - จัดเตรียมสภาพแวดล้อมที่คุณกำลังย้ายไปด้วยการกู้คืนการสำรองข้อมูลเต็มรูปแบบล่าสุดการสำรองข้อมูลส่วนต่างและการสำรองข้อมูลบันทึกที่ระบุไว้NORECOVERY- จากนั้นทั้งหมดที่คุณต้องทำเพื่อตัดสุดท้ายคือการคืนค่าการสำรองข้อมูลบันทึกที่ยังไม่ถูกกู้คืน WITH RECOVERYการสำรองข้อมูลเข้าสู่ระบบครั้งสุดท้ายที่คุณต้องการที่จะเรียกคืนระบุ วิธีนี้สำหรับฐานข้อมูลขนาดใหญ่หน้าต่างการหยุดทำงานของ cutover ที่เกิดขึ้นจริงสามารถลดลงได้อย่างมากด้วยการจ่ายค่าใช้จ่ายสำหรับการบันทึกที่เต็มความแตกต่างและส่วนใหญ่คืนค่าก่อนหน้าต่างการหยุดทำงาน ขอบคุณเต่าที่ชี้ให้เห็นในความคิดเห็น!

วิธีการทำให้การอัพเกรดภายในปลอดภัยยิ่งขึ้น

บางสิ่งที่คุณสามารถทำได้เพื่อปรับปรุงประสบการณ์และผลลัพธ์ของคุณเมื่อเลือกวิธีการเข้าแทนที่

  • การสำรองข้อมูล - ใช้การสำรองข้อมูลที่เหมาะสมของผู้ใช้และฐานข้อมูลระบบของสภาพแวดล้อมของคุณล่วงหน้าและให้แน่ใจว่าพวกเขาดี (ฉันหวาดระแวง .. ฉันจะคืนค่าพวกเขาก่อนที่จะรู้ว่าพวกเขาจะดี .. อาจเสียเวลาของคุณ . แต่คุณอาจขอบคุณตัวเองในกรณีที่เกิดภัยพิบัติ) .. เขียนข้อมูลการกำหนดค่าใด ๆ เกี่ยวกับการติดตั้ง SQL และ OS ที่สภาพแวดล้อมนั้น
  • ทดสอบสิ่งต่าง ๆ ให้ดีก่อนเริ่มต้น - ตรวจสอบว่าคุณมีสภาพแวดล้อมที่ดีและมีฐานข้อมูลที่ดี คุณควรทำสิ่งต่าง ๆ เช่นการดูบันทึกข้อผิดพลาดและเรียกใช้ DBCC CHECKDB เป็นประจำ แต่ก่อนที่จะทำการอัปเกรดแบบแทนที่จะเป็นการเริ่มต้นที่ดี แก้ไขปัญหาใด ๆ ล่วงหน้า
  • ตรวจสอบความถูกต้องของระบบปฏิบัติการ - อย่าเพิ่งตรวจสอบให้แน่ใจว่า SQL นั้นดีต่อสุขภาพตรวจสอบให้แน่ใจว่าเซิร์ฟเวอร์ของคุณแข็งแรง ข้อผิดพลาด gnarly ใด ๆ ในบันทึกเหตุการณ์ข้อผิดพลาดระบบหรือแอปพลิเคชันของคุณ? พื้นที่ว่างของคุณเป็นอย่างไร
  • เตรียมพร้อมสำหรับสิ่งที่เลวร้ายที่สุด - ฉันมีบล็อกโพสต์เมื่อไม่นานมานี้ที่ผ่านมาว่าถ้าคุณไม่เตรียมตัวสำหรับความล้มเหลว - คุณกำลังเตรียมที่จะล้มเหลวจริง ๆ .. ฉันยังเชื่ออย่างนั้น ดังนั้นให้คิดถึงปัญหาที่คุณอาจมีและจัดการกับปัญหาเหล่านั้นก่อนล่วงหน้า เข้าสู่ความคิดที่ "ล้มเหลว" แล้วคุณจะนึกถึงสิ่งต่าง ๆ ที่คุณไม่มี

ความสำคัญของการอัปเกรดหรือรายการตรวจสอบการย้ายข้อมูล

หากคุณตัดสินใจทำการอัปเกรด (ไม่ว่าจะอยู่ในสถานที่หรือย้ายข้อมูล) คุณควรพิจารณาสร้างรายการตรวจสอบอย่างจริงจังและใช้รายการตรวจสอบนี้ในแต่ละสภาพแวดล้อม คุณควรรวมสิ่งต่าง ๆ ไว้ในรายการตรวจสอบนี้ไม่ใช่อย่างน้อย:

  1. เมื่อเริ่ม - ทำบางสิ่งเช่นทำการทดสอบอัปเกรดทดสอบแอปพลิเคชันของคุณในระดับความเข้ากันได้ของฐานข้อมูลล่าสุดและพิจารณาใช้เครื่องมือเช่นSQL Server Upgrade Advisorล่วงหน้าเพื่อดูว่างานประเภทใดที่คุณต้องทำก่อนทำ SQL การอัพเกรดหรือการย้ายเซิร์ฟเวอร์
  2. ขั้นตอนพื้นฐาน - การล้างข้อมูล, งานระบบปฏิบัติการ, แก้ไขล่วงหน้า, เตรียมแอพพลิเคชั่นสำหรับการอัพเกรด (ปิดระบบใหม่ทั้งหมด, ทำงานสตริงการเชื่อมต่อ), สำรองข้อมูลฯลฯ
  3. ขั้นตอนการอัปเกรด / การย้ายข้อมูล - ทุกสิ่งที่คุณต้องทำเพื่อให้การอัปเกรดหรือการย้ายข้อมูลสำเร็จและเป็นไปตามลำดับที่ถูกต้อง การติดตั้งการเปลี่ยนแปลง (หรือไม่เปลี่ยนแปลงขึ้นอยู่กับการทดสอบและวิธีการของคุณ) การเปลี่ยนโหมดความเข้ากันได้กับฐานข้อมูล ฯลฯ
  4. โพสต์การโยกย้าย / ขั้นตอนการอัพเกรด - การทดสอบต่าง ๆ โพสต์รุ่นใหม่หรือตัวเลือกการกำหนดค่าเซิร์ฟเวอร์ใหม่การปฏิบัติที่ดีที่สุดการเปลี่ยนแปลงความปลอดภัย ฯลฯ
  5. ขั้นตอนการย้อนกลับ - ตลอดเส้นทางที่คุณควรมีขั้นตอนการย้อนกลับและเหตุการณ์สำคัญ ถ้าคุณได้รับสิ่งนี้และสิ่งนี้เกิดขึ้นคุณจะทำอะไร? เกณฑ์ "ทำแบบย้อนกลับ" คืออะไร และคุณจะย้อนกลับอย่างไร (เปลี่ยนสตริงการเชื่อมต่อย้อนกลับเปลี่ยนการตั้งค่าย้อนกลับกลับไปเป็นเวอร์ชั่นเก่าติดตั้งใหม่ถ้ามีอยู่ให้ชี้ไปที่เซิร์ฟเวอร์เก่าถ้ามีการโยกย้าย ฯลฯ )

แล้วให้คนที่จะทำการอัพเกรดการผลิตติดตามรายการตรวจสอบในสภาพแวดล้อมอื่นนอกเหนือจากการผลิต - โดยเฉพาะอย่างยิ่งที่ปิดการผลิตคล้ายกับการผลิตถ้าเป็นไปได้ ("ใต้ของแยง" ตามที่ฉันพูด ... ) และบันทึกปัญหาหรือประเด็นใด ๆ ที่พวกเขาต้องเบี่ยงเบนไปจากรายการตรวจสอบหรือโพล่งออกเพราะขาดในรายการตรวจสอบ จากนั้นรับการเปลี่ยนแปลงที่ผสานและสนุกกับการเปลี่ยนแปลงการผลิตของคุณ

ฉันไม่สามารถเน้นความสำคัญของการทดสอบอย่างละเอียดหลังการโยกย้ายหรืออัปเกรดและก่อนการโยกย้ายของคุณเพียงพอ การตัดสินใจย้อนกลับในระหว่างการอัปเกรดควรเป็นเรื่องง่ายโดยเฉพาะในระหว่างการย้ายข้อมูล หากมีบางอย่างไม่สบายใจให้ย้อนกลับและคิดออกว่าคุณไม่สามารถแก้ไขปัญหาได้อย่างมีประสิทธิภาพและเชื่อถือได้ในความร้อนของการย้ายถิ่น เมื่อคุณอยู่ในสภาพแวดล้อมใหม่นี้และผู้ใช้เชื่อมต่อการย้อนกลับกลายเป็นงานที่ยาก คุณไม่สามารถกู้คืนฐานข้อมูล SQL Server เป็นเวอร์ชันก่อนหน้า นั่นหมายถึงการย้ายข้อมูลด้วยตนเองและข้อมูล ฉันมักจะรอสองสามสัปดาห์เพื่อฆ่าสภาพแวดล้อมแบบเก่า แต่คุณควรทำทุกอย่างเท่าที่ทำได้เพื่อหลีกเลี่ยงความต้องการสภาพแวดล้อมแบบเดิมโดยการค้นหาปัญหาทั้งหมดของคุณก่อนที่ผู้ใช้สดของคุณจะได้สัมผัสกับสภาพแวดล้อมใหม่ โดยเฉพาะอย่างยิ่งก่อนที่คุณจะเริ่มการอัปเกรด / ย้ายข้อมูล

บันทึกย่อเกี่ยวกับการโยกย้าย / อัปเกรดบริการรายงานของ SQL Server Reporting การโอน ย้ายการติดตั้ง SSRS ไม่ใช่งานที่ต้องทำที่หลายคนคิดว่าเป็น นี้TechNet / หนังสือบทความออนไลน์เป็นจริงค่อนข้างสะดวก หนึ่งในคำเตือนที่สำคัญที่สุดในบทความนั้นคือ"สำรองคีย์การเข้ารหัส"โดยเฉพาะอย่างยิ่งถ้าคุณมีข้อมูลที่สำคัญมากมายที่บันทึกไว้เช่นอีเมลรายงานผู้รับตามกำหนดเวลาที่อยู่อีเมลข้อมูลการเชื่อมต่อสำหรับการเชื่อมต่อที่หลากหลายเป็นต้น สามารถถามลูกค้าของฉันสักครู่หนึ่งว่ามันสำคัญแค่ไหน พวกเขารู้เพราะฉันทำขั้นตอนนั้นยุ่งยากและใช้เวลาค่อนข้างมากในการแก้ไขกำหนดการรายงานและการอนุญาตการเชื่อมต่อสตริง


14

จากประสบการณ์ของฉันกระบวนการตัดสินใจแบบเดียวกันควรทำก่อน AFAIK ไม่มี 'ผู้เปลี่ยนโลก' ที่มีการติดตั้ง SQL Server ภายในผลิตภัณฑ์ MS SQL Server ในตัวของมันเองและปัญหาที่อาจเกิดขึ้นกับคุณเมื่อเปิดตัวซอฟต์แวร์ที่มีโค้ดหลายล้านบรรทัด มีบางอย่างไม่ดีเกิดขึ้นและตอนนี้คุณไม่มีตัวเลือก 'ย้อนกลับ'

อย่างไรก็ตามคุณมีทางเลือกอื่น ๆ คุณสามารถลองสร้างภาพรวมของระบบคืนค่าที่อื่นทำการอัพเกรดและดูว่าเกิดอะไรขึ้น การทดสอบนี้ควรให้ความสะดวกสบายแก่คุณเป็นอย่างมาก แต่ไม่รับประกันว่าจะไม่มีปัญหาใด ๆ เกิดขึ้นในกล่องผลิตภัณฑ์ อย่างไรก็ตามนี่เป็นตัวเลือกที่ไม่สามารถใช้งานได้ใน SQL 6.5 วัน

ฉันแค่จะสมมติสถานการณ์กรณีที่เลวร้ายที่สุด คุณทำการอัปเกรดแบบแทนที่และจะล้มเหลวอย่างน่าสังเวช คุณต้องกู้คืนจากสิ่งนี้ภายใน RTO และ RCO ของคุณ ธุรกิจเข้าใจความเสี่ยงและคุณมีแผนในการลดความเสี่ยงหรือไม่?

หากธุรกิจไม่ตกลงกับสิ่งนี้อย่าทำตามคำแนะนำของฉัน


2

หากคุณมีเซิร์ฟเวอร์ของคุณทำงานในสภาพแวดล้อมเสมือนคุณสามารถทำการถ่ายภาพบนโคลนจากนั้นใช้การอัปเกรดแบบแทนที่และทดสอบอินสแตนซ์เพื่อตรวจสอบว่าการอัพเกรดสำเร็จ หากใช้งานได้คุณสามารถใช้สแน็ปช็อตและสร้างโคลนเซิร์ฟเวอร์ที่ใช้งานจริง หากไปไม่ดีคุณสามารถลบสแนปชอตและกลับไปที่อิมเมจการอัปเกรดล่วงหน้าเพื่อลองอีกครั้งหรือลบโคลนและการโอนย้ายแบบเต็ม


1
เฉพาะในกรณีที่การจัดเก็บข้อมูลเสมือนจริงและเป็นส่วนหนึ่งของภาพรวม หากที่เก็บข้อมูลเชื่อมต่อโดยตรงกับ VM จะไม่ถูก 'ย้อนกลับ' เมื่อสแน็ปช็อตได้รับการกู้คืน ...
Remus Rusanu

1

เนื่องจากการลงทุนฮาร์ดแวร์จำนวนมากเราจำเป็นต้องอัพเกรดระบบปฏิบัติการในขณะที่รักษา SQL Server รุ่นปัจจุบัน (2012, 3 เซิร์ฟเวอร์, 22 ครั้ง, ~ 300 ฐานข้อมูล) ไม่มีการตั้งค่าที่ซับซ้อนเช่นการมิเรอร์ ฯลฯ

ตัวอย่างนี้ไม่ตรงกับคำถามเนื่องจาก SQL Server ไม่ได้รับการอัพเกรด ฉันคิดว่านี่ยังคงเป็นคำตอบที่ดีเพราะขั้นตอนที่แสดงจะง่ายกว่าการย้ายถิ่นจริง

ภาพรวม: มีการเชื่อมต่อไดรฟ์ภายนอกเพื่อสำรองข้อมูลเต็มรูปแบบเป็นหลักเพื่อความไม่ประมาท เฉพาะรุ่นและ msdb เท่านั้นที่จะกู้คืนจากไดรฟ์ภายนอก ldf / mdf ถูกทิ้งไว้เพื่อถอด / แนบ บัญชีท้องถิ่นบางบัญชีถูกอ้างอิงภายในฐานข้อมูล หลังจากที่พวกเขาถูกสร้างขึ้นใหม่ในระบบปฏิบัติการการอ้างอิงภายในฐานข้อมูลถูกสร้างขึ้นใหม่ (เนื่องจาก SID อาจมีการเปลี่ยนแปลง)

จากนั้นนี่คือขั้นตอนที่เหมาะกับเรา:

1) จดการตั้งค่าระดับเซิร์ฟเวอร์ซึ่งจะกู้คืนในขั้นตอนที่ 12 (บทบาทเซิร์ฟเวอร์) และ 18 ถึง 23

2) Patch SQL Server 2012 เป็น SP3 (จำเป็นต้องมีความสอดคล้องหากเราต้องการกู้คืนระบบ dbs ใด ๆ )

3) ตรวจสอบรุ่นที่ตรงกันในแต่ละอินสแตนซ์ "เลือกรุ่น @@"

4) สร้าง 6 สคริปต์เหล่านี้โดยเรียกใช้สคริปต์นี้ Redgate SQL Multiscript เป็นตัวจับเวลาขนาดใหญ่หากมีหลายอินสแตนซ์ (ปรับเครื่องมือ -> ตัวเลือก => ความยาวบรรทัดเป็นสูงสุด (8192) จากนั้นใช้เอาต์พุตข้อความ)

  • การสำรองข้อมูล
  • ฟื้นฟู
  • ถอดออก
  • แนบ
  • สร้างการเข้าสู่ระบบใหม่
  • เชื่อมโยงผู้ใช้กับการเข้าสู่ระบบอีกครั้ง

    -- (1) BACKUP / (2) RESTORE
    --    
    --*** SET THESE to external drive location
    --*** and create the Destination Directories
    declare 
        @backupInstanceDir  varchar(300) = 'F:\ExternalDriveBackups\' + replace(@@servername, '\', '_'),
        @dateSuffix         varchar(100) = '2015-12-14'; 
    
    if (object_id('tempdb..DatabaseStatus') is not null)
    drop table #DAtabseSTatus;
    
    select 
        d.name DbName, 
        d.state_desc DbState,
        d.user_access_desc UserMode,
        convert(bit, (d.is_read_only * -1 + 1)) as IsWritable,
        d.is_trustworthy_on as IsTrustWorthy,
        d.is_in_standby IsInStandby,
        d.recovery_model_desc RecoveryModel,
        suser_sname(d.owner_sid) as Owner,
        convert(bit, 
            case when d.database_id <= 4 or d.is_distributor = 1
                then 1
                else 0
            end) as IsSystemDb,
        mf.type_desc as FileType,
        mf.name FileName,
        mf.state FileState,
        mf.state_desc FileStatDesc,
        mf.physical_name PhysicalName,
        mf.type as FileTypeId    
    into #DatabaseStatus
    from
        sys.master_files AS mf
    join sys.databases AS d
    ON  mf.database_id = d.database_id
    where
        1=1
    order by
        d.name,
        mf.physical_name;
    
    if object_id('tempdb..#sqlOut') is not null
        drop table #sqlOutBU
    
    if object_id('tempdb..#sqlOut') is not null
        drop table #sqlOutRE
    
    create table #sqlOutBU
    (
        Command nvarchar(max) not null,
        Row int identity(1,1) not null primary key
    );
    
    create table #sqlOutRE
    (
        Command nvarchar(max) not null,
        Row int identity(1,1) not null primary key
    );
    
    insert into #sqlOutBU select char(10) + '-- BACKUP SCRIPT' + char(10);
    insert into #sqlOutRE select char(10) + '-- RESTORE SCRIPT' + char(10);
    
    
    insert into #sqlOutBU select char(10) + char(10) + '/* ---------------------------------------------------------------------------------------------' + char(10) + 
    'ServerName: ' + @@servername + char(10) + 'ServiceName: ' + @@servicename + char(10) + 'Version: ' + @@version + 
    '--------------------------------------------------------------------------------------------- */';
    
    insert into #sqlOutRE select char(10) + char(10) + '/* ---------------------------------------------------------------------------------------------' + char(10) + 
    'ServerName: ' + @@servername + char(10) + 'ServiceName: ' + @@servicename + char(10) + 'Version: ' + @@version + 
    '--------------------------------------------------------------------------------------------- */';        
    
    PRINT '--Script for Backing up all DBs in a SQL Server Instance to a specific location' 
    
    SET nocount ON 
    
    insert into #sqlOutBU select char(10) + 
    '--' + char(10) + '-- BACKUP ' + @@servername + '--' + char(10) + 
    'use [Master]; set deadlock_priority high;' + char(10);
    
    insert into #sqlOutRE select '
    -- RESTORE
    --
    -- BE SURE TO BACKUP SYSTEM DBS TO AN ALTERNATE LOCATION JUST BEFORE RESTORING!
    --
    use [Master]; set deadlock_priority high;' + char(10);
    
    DECLARE @dbname nvarchar(128) 
    declare dblist_cursor cursor fast_forward for 
    select [name] from master.sys.databases where [name] != 'tempdb'
    order by iif(database_id <= 4, '0', '1') + [name]
    
    open dblist_cursor 
    fetch next from dblist_cursor into @dbname 
    
    while @@fetch_status = 0 
    begin 
    
        declare @bak nvarchar(300) = @backupInstanceDir + '\' + @dbname + '_' + @dateSuffix + '.bak';
    
        insert into #sqlOutBU select char(10) + 'backup database [' + @dbname + '] to disk = ''' + @bak + ''' WITH COPY_ONLY, NOFORMAT, NOINIT, ' + char(10) + 
            'NAME = N''' + @dbName + '-Full'', SKIP, NOREWIND, NOUNLOAD, COMPRESSION, STATS = 25;';
    
        insert into #sqlOutRE select 'restore database [' + @dbName + '] from disk = ''' + @bak + ''' WITH FILE = 1,' + char(10) +
        (
            select '    move ''' + FileName + ''' to ''' + PhysicalName + '''' From #DatabaseStatus
            where FileType = 'Rows' and DbName = @dbName
        ) + ',' + char(10) +
        (
            select '    move ''' + FileName + ''' to ''' + PhysicalName + '''' From #DatabaseStatus
            where FileType = 'Log' and DbName = @dbName
        ) + ',' + char(10) +
        '    NOUNLOAD, REPLACE, STATS = 25;' + char(10);               
    
        fetch next from dblist_cursor into @dbname 
    end 
    
    close dblist_cursor 
    deallocate dblist_cursor 
    
    insert into #sqlOutBU select char(10) + 'go' + char(10);
    insert into #sqlOutRE select char(10) + 'go' + char(10);
    
    select Command from #sqlOutBU order by Row; -- BACKUP SCRIPT
    select Command from #sqlOutRE order by Row; -- RESTORE SCRIPT
    
    go
    
    
    
    --
    -- (3) DETACH  -  Org Author: Artemakis Artemiou
    --      
    
    if object_id('tempdb..#sqlOutDT') is not null
        drop table #sqlOutDT
    
    create table #sqlOutDT
    (
        Command nvarchar(max) not null,
        Row int identity(1,1) not null primary key
    );
    
    insert into #sqlOutDT select char(10) + '-- DETACH all DBs from a SQL Server Instance' + char(10);      
    
    insert into #sqlOutDT select char(10) + char(10) + '/* ---------------------------------------------------------------------------------------------' + char(10) + 
    'ServerName: ' + @@servername + char(10) + 'ServiceName: ' + @@servicename + char(10) + 'Version: ' + @@version + 
    '--------------------------------------------------------------------------------------------- */';
    
    SET nocount ON 
    
    insert into #sqlOutDT select char(10) + '--' + char(10) + '-- DETACH ' + @@servername + char(10) + '--' + char(10) + '
    use MAster; set deadlock_priority high;' + char(10) + char(10);
    
    DECLARE @dbname nvarchar(128) 
    DECLARE dblist_cursor CURSOR fast_forward FOR 
    SELECT [name] 
    FROM   master.sys.databases 
    WHERE  database_id > 4 
    
    OPEN dblist_cursor 
    FETCH next FROM dblist_cursor INTO @dbname 
    
    WHILE @@FETCH_STATUS = 0 
    BEGIN 
        insert into #sqlOutDT select
        'alter database ' + @dbname + ' set single_user with rollback immediate;' + char(10) +
        'EXEC sp_detach_db ''' + @dbname + ''', ''true'';' + char(10);
        FETCH next FROM dblist_cursor INTO @dbname 
    END 
    
    CLOSE dblist_cursor 
    DEALLOCATE dblist_cursor 
    
    insert into #sqlOutDT select char(10) + 'go' + char(10);
    select Command from #sqlOutDT order by Row;
    
    go
    
    
    
    --
    -- (4) ATTACH  -  Org Author: Artemakis Artemiou
    --    
    
    if object_id('tempdb..#sqlOut') is not null
        drop table #sqlOutAT
    
    create table #sqlOutAT
    (
        Command nvarchar(max) not null,
        Row int identity(1,1) not null primary key
    );
    
    insert into #sqlOutAT select char(10) + '-- ATTACH ALL DBs to a SQL Server Instance' + char(10);
    
    insert into #sqlOutAT select char(10) + char(10) + '/* ---------------------------------------------------------------------------------------------' + char(10) + 
    'ServerName: ' + @@servername + char(10) + 'ServiceName: ' + @@servicename + char(10) + 'Version: ' + @@version + 
    '--------------------------------------------------------------------------------------------- */';
    
    SET NOCOUNT ON
    
    insert into #sqlOutAT select char(10) + '--' + char(10) + '-- ATTACH ' + @@servername + char(10) + '--' + char(10) + 
    'use MAster;' + char(10) + char(10);
    
    DECLARE @dbname nvarchar(128);
    
    DECLARE DBList_cursor CURSOR fast_forward FOR 
    select [name] from master.sys.databases where database_id > 4
    order by name;
    
    OPEN DBList_cursor
    
    FETCH NEXT FROM DBList_cursor 
    INTO @dbname
    
    WHILE @@FETCH_STATUS = 0
    BEGIN
    
    declare @attach_TSQL_script varchar(max)
    set @attach_TSQL_script=''
    set @attach_TSQL_script=@attach_TSQL_script+'CREATE DATABASE ' + @dbname +' ON ' 
    
    declare @tsql varchar(max),@filename varchar(max)
    set @tsql='DECLARE DBFiles_cursor CURSOR FOR select [filename] from '+ @dbname + '.sys.sysfiles'
    
    execute (@tsql) 
    
    PRINT '--'+@dbname 
    
    OPEN DBFiles_cursor
    FETCH NEXT FROM DBFiles_cursor INTO @filename
    
    WHILE @@FETCH_STATUS = 0
    BEGIN   
    set @attach_TSQL_script=@attach_TSQL_script+ char(10)+'    (FILENAME = '''+ @filename +'''),' 
    FETCH NEXT FROM DBFiles_cursor INTO @filename
    END
    
    set @attach_TSQL_script=SUBSTRING(@attach_TSQL_script,0,len(@attach_TSQL_script))
    set @attach_TSQL_script=@attach_TSQL_script+ char(10) +'    FOR ATTACH;';
    
    insert into #sqlOutAT select @attach_TSQL_script + char(10);
    
    PRINT @attach_TSQL_script 
    PRINT ''
    
    CLOSE DBFiles_cursor
    DEALLOCATE DBFiles_cursor
    
    FETCH NEXT FROM DBList_cursor 
    INTO @dbname
    
    END 
    
    CLOSE DBList_cursor
    DEALLOCATE DBList_cursor
    
    insert into #sqlOutAT select char(10) + 'go' + char(10);
    select Command from #sqlOutAT order by Row;
    go
    
    
    
    --
    -- (5) GENERATE A 'RE-CREATE LOGINS' SCRIPT
    --
    -- This script was modified from a version that was designed to copy from one server to another:
    --      http://stackoverflow.com/a/5983773/538763
    --
    
    
    USE [master]
    
    if object_id('tempdb..#sqlOut') is not null
    drop table #sqlOut;
    
    create table #sqlOut
    (
    Command nvarchar(max) not null,
    Row int identity(1,1) not null primary key
    );
    
    insert into #sqlOut select char(10) + '-- RECREATE LOGINS' + char(10);
    
    
    insert into #sqlOut select char(10) + char(10) + '/* ---------------------------------------------------------------------------------------------' + char(10) + 
    'ServerName: ' + @@servername + char(10) + 'ServiceName: ' + @@servicename + char(10) + 'Version: ' + @@version + 
    '--------------------------------------------------------------------------------------------- */';
    
    insert into #sqlOut select 'use Master;' + char(10);
    go
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    declare @Debug bit = 0;
    declare @PartnerServer varchar(100) = @@SERVICENAME;  -- use current server before it is shutdown (disabled below)
    
    declare
        @MaxID int,
        @CurrID int,
        @SQL nvarchar(max),
        @LoginName sysname,
        @IsDisabled int,
        @Type char(1),
        @SID varbinary(85),
        @SIDString nvarchar(100),
        @PasswordHash varbinary(256),
        @PasswordHashString nvarchar(300),
        @RoleName sysname,
        @Machine sysname,
        @PermState nvarchar(60),
        @PermName sysname,
        @Class tinyint,
        @MajorID int,
        @ErrNumber int,
        @ErrSeverity int,
        @ErrState int,
        @ErrProcedure sysname,
        @ErrLine int,
        @ErrMsg nvarchar(2048);
    
    declare @Logins Table (LoginID int identity(1, 1) not null primary key,
                        [Name] sysname not null,
                        [SID] varbinary(85) not null,
                        IsDisabled int not null,
                        [Type] char(1) not null,
                        PasswordHash varbinary(256) null)
    declare @Roles Table (RoleID int identity(1, 1) not null primary key,
                    RoleName sysname not null,
                    LoginName sysname not null)
    declare @Perms Table (PermID int identity(1, 1) not null primary key,
                    LoginName sysname not null,
                    PermState nvarchar(60) not null,
                    PermName sysname not null,
                    Class tinyint not null,
                    ClassDesc nvarchar(60) not null,
                    MajorID int not null,
                    SubLoginName sysname null,
                    SubEndPointName sysname null)
    
    Set NoCount On;
    
    If CharIndex('\', @PartnerServer) > 0
    Begin
    Set @Machine = LEFT(@PartnerServer, CharIndex('\', @PartnerServer) - 1);
    End
    Else
    Begin
    Set @Machine = @PartnerServer;
    End
    
    -- Get all Windows logins from principal server
    Set @SQL = 'Select P.name, P.sid, P.is_disabled, P.type, L.password_hash' + CHAR(10) +
        'From ' /*+ QUOTENAME(@PartnerServer) + '.*/ + 'master.sys.server_principals P' + CHAR(10) +
        'Left Join '/* + QUOTENAME(@PartnerServer) + '.*/ + 'master.sys.sql_logins L On L.principal_id = P.principal_id' + CHAR(10) +
        'Where P.type In (''U'', ''G'', ''S'')' + CHAR(10) +
        'And P.name <> ''sa''' + CHAR(10) +
        'And P.name Not Like ''##%''' + CHAR(10) +
        'and P.Name Not like ''NT SERVICE%''' + CHAR(10) +
        'And CharIndex(''' + @Machine + '\'', P.name) = 0;';
    
    Insert Into @Logins (Name, SID, IsDisabled, Type, PasswordHash)
    Exec sp_executesql @SQL;
    
    -- Get all roles from principal server
    Set @SQL = 'Select RoleP.name, LoginP.name' + CHAR(10) +
        'From '/* + QUOTENAME(@PartnerServer) + '.*/ + 'master.sys.server_role_members RM' + CHAR(10) +
        'Inner Join '/* + QUOTENAME(@PartnerServer) + .*/ +'master.sys.server_principals RoleP' +
        CHAR(10) + char(9) + 'On RoleP.principal_id = RM.role_principal_id' + CHAR(10) +
        'Inner Join '/* + QUOTENAME(@PartnerServer) + '.*/ + 'master.sys.server_principals LoginP' +
        CHAR(10) + char(9) + 'On LoginP.principal_id = RM.member_principal_id' + CHAR(10) +
        'Where LoginP.type In (''U'', ''G'', ''S'')' + CHAR(10) +
        'And LoginP.name <> ''sa''' + CHAR(10) +
        'And LoginP.name Not Like ''##%''' + CHAR(10) +
        'And LoginP.name Not Like ''NT SERVICE%''' + CHAR(10) +
        'And RoleP.type = ''R''' + CHAR(10) +
        'And CharIndex(''' + @Machine + '\'', LoginP.name) = 0;';
    
    Insert Into @Roles (RoleName, LoginName)
    Exec sp_executesql @SQL;
    
    -- Get all explicitly granted permissions
    Set @SQL = 'Select P.name Collate database_default,' + CHAR(10) +
        '   SP.state_desc, SP.permission_name, SP.class, SP.class_desc, SP.major_id,' + CHAR(10) +
        '   SubP.name Collate database_default,' + CHAR(10) +
        '   SubEP.name Collate database_default' + CHAR(10) +
        'From '/* + QUOTENAME(@PartnerServer) + '.*/ + ' master.sys.server_principals P' + CHAR(10) +
        'Inner Join '/* + QUOTENAME(@PartnerServer) + '.*/ + ' master.sys.server_permissions SP' + CHAR(10) +
        CHAR(9) + 'On SP.grantee_principal_id = P.principal_id' + CHAR(10) +
        'Left Join '/* + QUOTENAME(@PartnerServer) + '.*/ + ' master.sys.server_principals SubP' + CHAR(10) +
        CHAR(9) + 'On SubP.principal_id = SP.major_id And SP.class = 101' + CHAR(10) +
        'Left Join '/* + QUOTENAME(@PartnerServer) + '.*/ + ' master.sys.endpoints SubEP' + CHAR(10) +
        CHAR(9) + 'On SubEP.endpoint_id = SP.major_id And SP.class = 105' + CHAR(10) +
        'Where P.type In (''U'', ''G'', ''S'')' + CHAR(10) +
        'And P.name <> ''sa''' + CHAR(10) +
        'And P.name Not Like ''##%''' + CHAR(10) +
        'And P.name Not Like ''NT SERVICE%''' + CHAR(10) +
        'And CharIndex(''' + @Machine + '\'', P.name) = 0;'
    
    Insert Into @Perms (LoginName, PermState, PermName, Class, ClassDesc, MajorID, SubLoginName, SubEndPointName)
    Exec sp_executesql @SQL;
    
    --select * from @Logins;
    --select * from @Roles;
    --select * from @perms;
    
    
    Select @MaxID = Max(LoginID), @CurrID = 1
    From @Logins;
    
    While @CurrID <= @MaxID
    Begin
    Select @LoginName = Name,
        @IsDisabled = IsDisabled,
        @Type = [Type],
        @SID = [SID],
        @PasswordHash = PasswordHash
    From @Logins
    Where LoginID = @CurrID;
    
    --    If Not Exists (Select 1 From sys.server_principals
    --              Where name = @LoginName)
    Begin
    
        set @sql = char(10);
        set @sql += 'If Not Exists (Select 1 From sys.server_principals Where name = ''' + @LoginName + ''')' + char(10);
        set @sql += 'begin' + char(10) + '    ';
    
        Set @SQL += 'Create Login ' + quotename(@LoginName)
        If @Type In ('U', 'G')
        Begin
            Set @SQL = @SQL + ' From Windows;'
        End
        Else
        Begin
            Set @PasswordHashString = '0x' +
                Cast('' As XML).value('xs:hexBinary(sql:variable("@PasswordHash"))', 'nvarchar(300)');
    
            Set @SQL = @SQL + ' With Password = ' + @PasswordHashString + ' HASHED;  --, ';
    
            Set @SIDString = '0x' +
                Cast('' As XML).value('xs:hexBinary(sql:variable("@SID"))', 'nvarchar(100)');
            Set @SQL = @SQL + 'SID = ' + @SIDString + ';' + char(10);
        End
    
        set @sql += char(10) +
            '    print ''Created Login ' + @loginName  + ''';' + char(10) +
            'end' + char(10) +
            'else' + char(10) +
            convert(nvarchar(max), '    print ''Login ' + @loginName + ' already existed. '';') + char(10);
    
        If @Debug = 0
        insert into #sqlOut select @SQL;                      
        Else
        Print @SQL;
    
        If @IsDisabled = 1
        Begin
            Set @SQL = 'Alter Login ' + quotename(@LoginName) + ' Disable;'
            If @Debug = 0
                insert into #sqlOut select @SQL;                              
            Else              
                Print @SQL;              
        End
        End
    Set @CurrID = @CurrID + 1;
    End
    
    
    insert into #sqlOut select char(10) + 'use Master;' + char(10);
    
    Select @MaxID = Max(RoleID), @CurrID = 1
    From @Roles;
    
    While @CurrID <= @MaxID
    Begin
    Select @LoginName = LoginName,
        @RoleName = RoleName
    From @Roles
    Where RoleID = @CurrID;
    
    /*  If Not Exists (Select 1 From sys.server_role_members RM
                Inner Join sys.server_principals RoleP
                    On RoleP.principal_id = RM.role_principal_id
                Inner Join sys.server_principals LoginP
                    On LoginP.principal_id = RM.member_principal_id
                Where LoginP.type In ('U', 'G', 'S')
                And RoleP.type = 'R'
                And RoleP.name = @RoleName
                And LoginP.name = @LoginName)*/
    Begin
        If @Debug = 0
        Begin          
            insert into #sqlOut select 'Exec sp_addsrvrolemember @rolename = ''' + @RoleName + ''', @loginame = ''' + @LoginName + ''';';
        End
        Else
        Begin
            Print 'Exec sp_addsrvrolemember @rolename = ''' + @RoleName + ''',';
            Print '     @loginame = ''' + @LoginName + ''';';
        End
    End
    
    Set @CurrID = @CurrID + 1;
    End
    
    
    insert into #sqlOut select char(10) + 'use Master;' + char(10);
    
    
    Select @MaxID = Max(PermID), @CurrID = 1
    From @Perms;
    
    While @CurrID <= @MaxID
    Begin
    Select @PermState = PermState,
        @PermName = PermName,
        @Class = Class,
        @LoginName = LoginName,
        @MajorID = MajorID,
        @SQL = PermState + space(1) + PermName + SPACE(1) +
            Case Class When 101 Then 'On Login::' + QUOTENAME(SubLoginName)
                    When 105 Then 'On ' + ClassDesc + '::' + QUOTENAME(SubEndPointName)
                    Else '' End +
            ' To ' + QUOTENAME(LoginName) + ';'
    From @Perms
    Where PermID = @CurrID;
    
    /*If Not Exists (Select 1 From sys.server_principals P
                Inner Join sys.server_permissions SP On SP.grantee_principal_id = P.principal_id
                Where SP.state_desc = @PermState
                And SP.permission_name = @PermName
                And SP.class = @Class
                And P.name = @LoginName
                And SP.major_id = @MajorID)*/
    Begin
        If @Debug = 0
                insert into #sqlOut select @sql;                      
        Else          
            Print @SQL;          
    End
    
    Set @CurrID = @CurrID + 1;
    End
    
    
    select Command from #sqlOut as SqlOut order by Row;
    go
    
    
    --
    -- (6) Generate a script to Re-link all users to logins based on current state (before shutdown)
    --
    
    use Master;
    
    if object_id('tempdb..#sqlOut') is not null
    drop table #sqlOut;
    
    create table #sqlOut
    (
        Command nvarchar(max) not null,
        Row int identity(1,1) not null primary key
    );
    
    insert into #sqlOut select char(10) + '-- RELINK USERS TO LOGINS' + char(10);
    
    insert into #sqlOut select char(10) + char(10) + '/* ---------------------------------------------------------------------------------------------' + char(10) + 
    'ServerName: ' + @@servername + char(10) + 'ServiceName: ' + @@servicename + char(10) + 'Version: ' + @@version + 
    '--------------------------------------------------------------------------------------------- */';
    
    declare @dbCmd varchar(8000) = '
    use ?;
    
    insert into #sqlOut select char(10) + ''use ?;'' + char(10);  
    
    with links as
    (
    select u.name as UserName,
        l.loginname as LoginName
        from sysusers u 
        join master..syslogins l
        on u.sid = l.sid        
    where u.name != ''dbo''
        and u.isSqlUser = 1 or l.isNtName = 1 or l.isNtGroup = 1
    )
    insert into #sqlOut 
    select ''alter user ['' + UserName + ''] with name = ['' + UserName + ''], login = ['' + LoginName + '']''
    from links
    ';    
    
    exec sp_MSforeachdb @dbCmd;
    
    select Command from #sqlOut order by Row;
    
    go

5) เรียกใช้สคริปต์เพื่อสำรองฐานข้อมูลทั้งหมดรวมถึงระบบ (master, msdb, model) ไปยังไดรฟ์ภายนอก

6) เรียกใช้สคริปต์เพื่อแยก DBs ทั้งหมด

7) C Drive จะถูกฟอร์แมตใหม่ รักษา LDF / MDF ถ้าไม่ได้อยู่บน C.

8) ติดตั้ง Windows Server 2012 บน C

9) ย้าย LDF / MDF สำหรับไฟล์ระบบดั้งเดิมออกไปหากไม่ได้อยู่ในไดรฟ์ C

10) SQL Server 2012 จะถูกติดตั้งใหม่และได้รับการติดตั้ง SP3 a สร้างบัญชีผู้ใช้ / กลุ่มระบบอีกครั้ง

11) DB ระบบสำรองข้อมูลไปยังตำแหน่งใหม่หรือชื่อไฟล์ (ระวังอย่าเขียนทับต้นฉบับ!)

12) เรียกใช้สร้างส่วนย่อยของบทบาทใหม่ สิ่งที่ต้องการ:

USE [master]
CREATE SERVER ROLE [SomeServerRole]
--ALTER SERVER ROLE [dbcreator] ADD MEMBER [SomeServerRole]
--ALTER SERVER ROLE [bulkadmin] ADD MEMBER [SomeServerRole]
-- ALTER SERVER ROLE [SomeServerRole] ADD MEMBER [SomeMemberOrRole]

13) เรียกใช้สคริปต์การเข้าสู่ระบบอีกครั้ง

14) หยุดตัวแทน SQL

(สามารถเรียกคืนปริญญาโทได้ที่นี่เราทำให้ไก่ออกไป)

15) แนบ mdf / ldf โดยใช้สคริปต์จากด้านบน หากล้มเหลวในการกู้คืนด้วยตนเองจาก bak โดยใช้สคริปต์จากด้านบน

16) ความพยายามคืนค่าของรุ่น

17) ให้แน่ใจว่า SQL Agent หยุดทำงาน กู้คืน MSDB (ลิงค์) หากล้มเหลวจำเป็นต้องสร้างงานใหม่ + แผนการบำรุงรักษา + การกำหนดค่าจดหมาย + ตัวดำเนินการ

18) เปิดผู้ใช้เพื่อเข้าสู่ระบบสคริปต์ ...

    a. If there are master users (rare?) then First Re-Create users for master since it was not restored:
        use master;       
        CREATE USER [ABC] FOR LOGIN [machine\ABC]

    b. Run the rest of the script

19) เปิดใช้งานนายหน้าบริการเพื่อให้ตรงกับค่าชื่อ SELECT, is_broker_enabled จาก sys.d Database;

    alter database MSDB set single_user with rollback immediate;
    ALTER DATABASE [MSDB] SET ENABLE_BROKER;
    alter database MSDB set multi_user;

20) เริ่มตัวแทน SQL

21) ตั้งค่า Parallelism เป็นค่าเริ่มต้น

22) ปรับการตั้งค่าฐานข้อมูลให้เป็นค่าดั้งเดิม:

 declare @dbCmd varchar(8000) = '
      use ?;
      if db_name() not in (''master'', ''model'', ''tempdb'', ''msdb'')
      begin
             print ''Adjusting [?]...'';    
            alter database [?] set single_user with rollback immediate;
             aLTER AUTHORIZATION ON DATABASE::[?] to [sa];
            -- alter database [?] set trustworthy on;
            ALTER DATABASE [?] SET AUTO_CLOSE OFF WITH NO_WAIT;     
            alter database [?] set multi_user;
      end     
      else
             print ''Skipping [?]...'';
    ';    

    exec sp_MSforeachdb @dbCmd;

23) ตรวจสอบความเป็นเจ้าของงาน:

select s.name as JobName, l.name as login, SUSER_SNAME(s.owner_sid) AS login2
from  msdb..sysjobs s 
left join master.sys.syslogins l on s.owner_sid = l.sid

หากเวอร์ชันของเซิร์ฟเวอร์ SQL ได้รับการอัพเกรดด้วยฉันไม่เชื่อว่ารูปแบบและฐานข้อมูล msdb สามารถถูกกู้คืนได้ดังนั้นงานจะสูญหายเนื่องจาก https://support.microsoft.com/en-us/kb/264474

สิ่งที่ขาดหายไป:

  • ผู้ใช้ดั้งเดิมในฐานข้อมูลหลัก (หายาก?)
  • บทบาทเซิร์ฟเวอร์
  • ?

0

ไม่มีอะไรผิดปกติกับวิธีการอย่างใดอย่างหนึ่ง - ฉันได้ทำทั้งสองและผลลัพธ์ทั้งสองมักจะดี

หากมีปัญหาเกี่ยวกับวิธีการโยกย้ายก็ไม่ใช่ทางเทคนิค: มันเป็นความเกียจคร้าน บ่อยครั้งที่ฉันพบว่าเหตุผลที่ บริษัท ยังไม่ได้เป็นเวอร์ชัน xxxx อย่างเต็มที่ก็เพราะพวกเขาเลือกการโยกย้ายแบบวงสวิงและไม่เคยทำงานหนักเพื่อย้ายอย่างสมบูรณ์ ตอนนี้พวกเขามีเซิร์ฟเวอร์สองชุดขึ้นไปแทนที่จะเป็นหนึ่งชุด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.