Last active
October 12, 2024 16:36
-
-
Save alivarzeshi/0bc30386a53ae5cd3eea58fd382589fc to your computer and use it in GitHub Desktop.
Main Folder Security
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
DECLARE @IsPrimary INT; | |
DECLARE @JobName NVARCHAR(128); | |
-- Check if the current node is the primary replica | |
SELECT @IsPrimary = CASE | |
WHEN role_desc = 'PRIMARY' THEN 1 | |
ELSE 0 | |
END | |
FROM sys.dm_hadr_availability_replica_states AS ars | |
JOIN sys.availability_replicas AS ar | |
ON ars.replica_id = ar.replica_id | |
WHERE ars.is_local = 1; | |
-- If this node is primary, enable all jobs. If secondary, disable all jobs. | |
IF @IsPrimary = 1 | |
BEGIN | |
-- Enable all SQL Agent jobs | |
DECLARE @EnableJobs TABLE (JobName NVARCHAR(128)); | |
-- Insert all jobs into the temporary table | |
INSERT INTO @EnableJobs (JobName) | |
SELECT name | |
FROM msdb.dbo.sysjobs; | |
-- Enable all jobs in the table | |
WHILE EXISTS (SELECT * FROM @EnableJobs) | |
BEGIN | |
SELECT TOP 1 @JobName = JobName FROM @EnableJobs; | |
EXEC msdb.dbo.sp_update_job @job_name = @JobName, @enabled = 1; | |
PRINT 'Enabled ' + @JobName + ' on the primary replica'; | |
-- Remove the job from the table after processing | |
DELETE FROM @EnableJobs WHERE JobName = @JobName; | |
END | |
END | |
ELSE | |
BEGIN | |
-- Disable all SQL Agent jobs | |
DECLARE @DisableJobs TABLE (JobName NVARCHAR(128)); | |
-- Insert all jobs into the temporary table | |
INSERT INTO @DisableJobs (JobName) | |
SELECT name | |
FROM msdb.dbo.sysjobs; | |
-- Disable all jobs in the table | |
WHILE EXISTS (SELECT * FROM @DisableJobs) | |
BEGIN | |
SELECT TOP 1 @JobName = JobName FROM @DisableJobs; | |
EXEC msdb.dbo.sp_update_job @job_name = @JobName, @enabled = 0; | |
PRINT 'Disabled ' + @JobName + ' on the secondary replica'; | |
-- Remove the job from the table after processing | |
DELETE FROM @DisableJobs WHERE JobName = @JobName; | |
END | |
END |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
This query retrieves information about employees along with their associated projects, if any. | |
The OUTER APPLY operator ensures that all employees are listed, even if they have no associated projects. | |
*/ | |
SELECT | |
e.EmployeeID, | |
e.FirstName, | |
e.LastName, | |
p.ProjectName, | |
p.StartDate, | |
p.EndDate, | |
p.Budget | |
FROM | |
Employees e | |
OUTER APPLY | |
(SELECT ProjectName, StartDate, EndDate, Budget | |
FROM Projects | |
WHERE Projects.EmployeeID = e.EmployeeID) p; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
This query retrieves unique locations from both the Departments table and the combination of | |
Employees and Departments, avoiding duplicates by using UNION. | |
*/ | |
SELECT Location FROM Departments | |
UNION | |
SELECT d.Location | |
FROM Employees e | |
INNER JOIN Departments d ON e.DepartmentID = d.DepartmentID; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
This query retrieves all locations from both the Departments table and the combination of | |
Employees and Departments, including duplicates, using UNION ALL. | |
*/ | |
SELECT Location FROM Departments | |
UNION ALL | |
SELECT d.Location | |
FROM Employees e | |
INNER JOIN Departments d ON e.DepartmentID = d.DepartmentID; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
This query retrieves locations that are common between the Departments table and | |
the combination of Employees and Departments using INTERSECT. | |
*/ | |
SELECT Location FROM Departments | |
INTERSECT | |
SELECT d.Location | |
FROM Employees e | |
INNER JOIN Departments d ON e.DepartmentID = d.DepartmentID; |
Here's the revised version of your original code incorporating the recommendations for error handling, safe cursor usage, logging, and documentation. The updated script includes improved structure, error logging, and more robust logic to handle job enabling/disabling during failovers in an Always On Availability Group:
/*
Script Purpose:
This script enables or disables SQL Agent jobs based on the current server's role in an Always On Availability Group.
- If the server is the primary replica, it enables all SQL Agent jobs.
- If the server is the secondary replica, it disables all SQL Agent jobs.
Key Sections:
1. Determine if the server is primary or secondary.
2. Enable or disable jobs accordingly.
3. Error handling for both job processing and role detection.
4. Exclude any critical jobs from being disabled.
5. Enhanced logging for easier troubleshooting.
Author: [Your Name]
Date: [Current Date]
*/
BEGIN TRY
DECLARE @IsPrimary INT;
DECLARE @JobName NVARCHAR(128);
-- 1. Check if the current node is the primary replica
SELECT @IsPrimary = CASE
WHEN role_desc = 'PRIMARY' THEN 1
ELSE 0
END
FROM sys.dm_hadr_availability_replica_states AS ars
JOIN sys.availability_replicas AS ar
ON ars.replica_id = ar.replica_id
WHERE ars.is_local = 1;
-- Log the server role for troubleshooting
IF @IsPrimary IS NULL
BEGIN
PRINT 'Error determining whether this node is primary or secondary. Check AG configuration.';
RETURN; -- Optionally terminate script if the role cannot be determined
END
ELSE
BEGIN
PRINT 'Server is recognized as: ' + CASE WHEN @IsPrimary = 1 THEN 'Primary' ELSE 'Secondary' END;
END
-- 2. Enable jobs if this is the primary replica, disable jobs if this is the secondary replica
IF @IsPrimary = 1
BEGIN
PRINT 'This is the primary replica. Enabling all jobs.';
-- 3. Declare a cursor for all jobs in sysjobs, excluding critical jobs that should always be enabled
DECLARE JobCursor CURSOR FOR
SELECT name
FROM msdb.dbo.sysjobs
WHERE name NOT IN ('CriticalJob1', 'CriticalJob2'); -- Modify to exclude any critical jobs
OPEN JobCursor;
FETCH NEXT FROM JobCursor INTO @JobName;
-- Process each job: Enable on primary
WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN TRY
-- Enable the job
EXEC msdb.dbo.sp_update_job @job_name = @JobName, @enabled = 1;
PRINT 'Enabled job: ' + @JobName + ' on the primary replica.';
END TRY
BEGIN CATCH
-- Error handling for each job
PRINT 'Error enabling job: ' + @JobName;
PRINT 'Error Message: ' + ERROR_MESSAGE();
END CATCH;
-- Fetch next job
FETCH NEXT FROM JobCursor INTO @JobName;
END
-- Close and deallocate the cursor
CLOSE JobCursor;
DEALLOCATE JobCursor;
END
ELSE
BEGIN
PRINT 'This is the secondary replica. Disabling all jobs.';
-- 4. Declare a cursor for all jobs in sysjobs, excluding critical jobs that should always be enabled
DECLARE JobCursor CURSOR FOR
SELECT name
FROM msdb.dbo.sysjobs
WHERE name NOT IN ('CriticalJob1', 'CriticalJob2'); -- Modify to exclude any critical jobs
OPEN JobCursor;
FETCH NEXT FROM JobCursor INTO @JobName;
-- Process each job: Disable on secondary
WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN TRY
-- Disable the job
EXEC msdb.dbo.sp_update_job @job_name = @JobName, @enabled = 0;
PRINT 'Disabled job: ' + @JobName + ' on the secondary replica.';
END TRY
BEGIN CATCH
-- Error handling for each job
PRINT 'Error disabling job: ' + @JobName;
PRINT 'Error Message: ' + ERROR_MESSAGE();
END CATCH;
-- Fetch next job
FETCH NEXT FROM JobCursor INTO @JobName;
END
-- Close and deallocate the cursor
CLOSE JobCursor;
DEALLOCATE JobCursor;
END
END TRY
BEGIN CATCH
-- Global error handling for the entire script
PRINT 'An error occurred while processing jobs. Error details:';
PRINT 'Error Number: ' + CAST(ERROR_NUMBER() AS NVARCHAR(10));
PRINT 'Error Severity: ' + CAST(ERROR_SEVERITY() AS NVARCHAR(10));
PRINT 'Error State: ' + CAST(ERROR_STATE() AS NVARCHAR(10));
PRINT 'Error Procedure: ' + ISNULL(ERROR_PROCEDURE(), 'N/A');
PRINT 'Error Line: ' + CAST(ERROR_LINE() AS NVARCHAR(10));
PRINT 'Error Message: ' + ERROR_MESSAGE();
-- Optionally log the error to a table or alert system here
-- Example:
-- INSERT INTO dbo.JobExecutionLog (LogTime, JobName, Action, Message) VALUES (GETDATE(), @JobName, 'Error', ERROR_MESSAGE());
END CATCH;
Detailed Review of Changes:
-
Overall Comments:
- Added detailed comments to the script header and key sections, explaining the purpose of the script, logic, and the flow of the process.
- Each section (primary detection, job enable/disable, error handling) is clearly documented for easier understanding.
-
Global Error Handling:
- Enhanced the global
CATCH
block with detailed error information (error number, severity, state, procedure, and line) to provide complete debugging information. - This helps in diagnosing any issues that may occur during script execution.
- Enhanced the global
-
Primary/Secondary Detection:
- Added logging to print the server’s role (Primary/Secondary) for easier troubleshooting and monitoring.
- Added an early exit (
RETURN
) in case the role cannot be determined, which prevents further processing in an invalid state.
-
Cursors:
- Safe usage of cursors with proper
CLOSE
andDEALLOCATE
to ensure no resource leaks. - Improved error handling inside each cursor loop. If a job fails to be enabled or disabled, the error is caught and logged, but the rest of the jobs continue processing.
- Safe usage of cursors with proper
-
Exclusion of Critical Jobs:
- Added logic to exclude specific jobs (e.g.,
'CriticalJob1'
,'CriticalJob2'
) that should not be disabled/enabled. You can modify this list as needed for your environment. - This prevents critical jobs (e.g., monitoring jobs) from being inadvertently disabled.
- Added logic to exclude specific jobs (e.g.,
-
Logging:
PRINT
statements are included for interactive debugging, but an example of logging to a table (JobExecutionLog
) is provided in the comments. This could be useful for long-term tracking or integration with a monitoring system.
Testing and Deployment:
- Testing: It is crucial to test this script in a non-production environment where you can simulate failovers and ensure that jobs are enabled/disabled as expected.
- Performance: Ensure that the script runs efficiently with your number of jobs, especially if there are hundreds of jobs.
- Frequency: If this script will run frequently (e.g., every minute), monitor for any potential performance impact or conflicts with other scheduled tasks.
With these changes, the script is now robust, safe, and ready for a production environment, providing clear error handling, easy troubleshooting, and protection against resource leaks or unintended job disabling.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Tip
In-Depth Analysis of Miscellaneous Events in SQL Server Error Logs
Overview
Miscellaneous events in SQL Server error logs capture a variety of events that do not neatly fit into the predefined categories such as system events, database events, backup and restore events, security events, Always On Availability Groups events, replication events, agent job events, error and warning events, and performance and resource events. These miscellaneous events can include a wide range of occurrences, from custom application logs to third-party tool integrations and unusual server activities.
Structure of Miscellaneous Event Log Entries
Each log entry for miscellaneous events typically includes the following components:
Common Miscellaneous Events
1. Custom Application Logs
2. Third-Party Tool Integrations
3. Unusual Server Activities
Additional Relevant Information
Error Number Details
Error: 50000 (Custom Error)
Error: 60000 (Third-Party Integration Error)
Importance of Monitoring Miscellaneous Events
Background Processes and Mechanisms
Custom Logging
RAISEERROR
or by writing directly to SQL Server logs.Third-Party Tool Logging
Efficient Reading of Miscellaneous Logs
Using SQL Server Management Studio (SSMS):
Using T-SQL Commands:
Using Extended Events:
Automating Log Monitoring:
Conclusion
Miscellaneous events in SQL Server logs provide valuable insights into activities and issues that fall outside standard categories. Understanding the structure of these logs, common errors, and the internal processes behind them allows administrators to effectively monitor, troubleshoot, and manage SQL Server environments comprehensively. Regularly reviewing these logs ensures that all aspects of SQL Server's operation are covered, enhancing the overall reliability and efficiency of the SQL Server environment.