จะกรองการใช้ฟังก์ชันที่ผู้ใช้กำหนดเองของ Scalar จากข้อมูลการตรวจสอบเซิร์ฟเวอร์ SQL ได้อย่างไร


12

เรามีฐานข้อมูล SQL Server ซึ่งมีข้อกำหนดการตรวจสอบฐานข้อมูลที่ตรวจสอบการดำเนินการทั้งหมดในฐานข้อมูล

CREATE DATABASE AUDIT SPECIFICATION [dbAudit]
FOR SERVER AUDIT [servAudit]
ADD (EXECUTE ON DATABASE::[DatabaseName] BY [public])

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

น่าเสียดายเนื่องจากเหตุผลด้านความสอดคล้องเราไม่สามารถหยุดการตรวจสอบทุกEXECUTEคำสั่งได้

ความคิดแรกของเราสำหรับแนวทางในการแก้ไขปัญหานี้คือการใช้WHEREข้อในการตรวจสอบเซิร์ฟเวอร์เพื่อกรองกิจกรรม รหัสดูเหมือนว่านี้:

WHERE [object_id] not in (Select object_id from sys.objects where type = 'FN' )

น่าเสียดายที่ SQL Server ไม่อนุญาตให้ตัวดำเนินการสัมพันธ์ (อาจเป็นเพราะมันไม่ต้องการสอบถามทุกครั้งที่มีการเขียนไปยังบันทึกการตรวจสอบ)

เราต้องการหลีกเลี่ยงการเขียน proc ที่เก็บไว้ซึ่งเป็นรหัสที่ยากobject_idในWHEREข้อ แต่นั่นคือความคิดของเราในปัจจุบันเกี่ยวกับวิธีที่ดีที่สุดในการแก้ไขปัญหานี้ มีวิธีอื่นที่เราควรพิจารณาหรือไม่?

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

มีฟังก์ชั่น Scalar Valued บางฟังก์ชั่นที่จัดส่งโดยผู้จำหน่ายซึ่งเราไม่สามารถลบหรือย้ายไปยังฐานข้อมูลอื่นได้


6
We've found that some queries will write to the audit log the use of a scalar function for every row in a result set.- นั่นเป็นหนึ่งในผลข้างเคียงที่ยอดเยี่ยมที่สุดของ UDF สเกลาร์ที่ฉันเคยได้ยินและฉันได้ยินมามาก
Erik Darling

3
มีตัวเลือกในการสร้าง UDF หรือไม่ที่คุณไม่ต้องการให้มีการตรวจสอบในฐานข้อมูลแยกต่างหาก (ที่ไม่ผ่านการตรวจสอบ) และเรียกใช้พวกเขาผ่าน 3 ส่วนชื่อ?
Scott Hodgin

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

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

คำตอบ:


6

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

ขั้นแรกวิธีการทั่วไปที่สุดคือกรอง UDF สเกลาร์ทั้งหมดออก คุณสามารถทำได้โดยใช้class_typeฟิลด์การตรวจสอบ เอกสารประกอบระบุว่าฟิลด์นี้เป็นVARCHAR(2)แต่ไม่อนุญาตให้ระบุสตริง อย่างไรก็ตามฉันได้ทำงานต่อไปนี้:

ALTER SERVER AUDIT [servAudit]
WHERE ([class_type] <> 20038); -- EXECUTE Scalar UDF

(ข้อมูลเพิ่มเติมเกี่ยวกับการตรวจสอบที่นี่: การตรวจสอบเซิร์ฟเวอร์ลึกลับ: การกรอง class_type ได้รับข้อผิดพลาดข่าวสารเกี่ยวกับ 25713 )

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

วิธีการทั่วไปที่น้อยที่สุด (แต่วิธีที่ใช้ได้) คือการกรองชื่อฟังก์ชันเฉพาะ:

ALTER SERVER AUDIT [servAudit]
WHERE ([object_name]<>'function_name');

หรือหากมีหลายชื่อ:

ALTER SERVER AUDIT [servAudit]
WHERE ([object_name]<>'function_name1' AND [object_name]<>'function_name2');

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

ในที่สุดสำหรับผู้อื่นที่เผชิญสถานการณ์นี้และไม่ถูก จำกัด จากการเปลี่ยนแปลง: คุณสามารถวางฟังก์ชั่นไว้ในสคีมาของตัวเองแล้วกรองสคีมานั้นออก นี่เป็นเรื่องทั่วไปมากกว่าการกรองฟังก์ชั่นแยกต่างหาก สมมติว่าคุณสร้าง Schema ชื่อfnและวางฟังก์ชั่นไว้ในนั้น:

ALTER SERVER AUDIT [servAudit]
WHERE ([schema_name]<>'fn');

นอกจากนี้เกี่ยวกับสองความคิดเห็นต่อไปนี้ในคำถาม:

น่าเสียดายที่ SQL Server ไม่อนุญาตให้ตัวดำเนินการสัมพันธ์ (อาจเป็นเพราะมันไม่ต้องการสอบถามทุกครั้งที่มีการเขียนไปยังบันทึกการตรวจสอบ)

และ:

เราต้องการหลีกเลี่ยงการเขียน proc ที่เก็บไว้ซึ่งรหัสยาก object_id ในข้อ WHERE

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


ขอบคุณสำหรับคำตอบนี้ เราอยู่ในกระบวนการดำเนินการเปลี่ยนแปลงนี้และฉันจะยอมรับคำตอบนี้เมื่อเรายืนยันว่ามันทำงานในสภาพแวดล้อมของเรา
Mark Iannucci

1
@ MarkIannucci ขอบคุณ! นอกจากนี้ฉันเพิ่งแก้ไขข้อบกพร่องเล็กน้อยในคำแนะนำในอุดมคติของฉัน ฉันคัดลอกและวางจากการทดสอบที่ฉันกรองสำหรับฟังก์ชั่นแทนฟังก์ชั่นใด ๆ แต่ ผมเปลี่ยน=ให้เป็น<>ในคำตอบของฉัน ฉันเพิ่งทดสอบและใช้งานได้ตาม :-)
โซโลมอน Rutzky
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.