<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Mohamed Tharif on Medium]]></title>
        <description><![CDATA[Stories by Mohamed Tharif on Medium]]></description>
        <link>https://medium.com/@mohammedtharif30?source=rss-8851d255a5fa------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Stories by Mohamed Tharif on Medium</title>
            <link>https://medium.com/@mohammedtharif30?source=rss-8851d255a5fa------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Tue, 19 May 2026 19:11:26 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@mohammedtharif30/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[What Every SQL Server DBA Should Know About PostgreSQL Architecture]]></title>
            <link>https://medium.com/@mohammedtharif30/what-every-sql-server-dba-should-know-about-postgresql-architecture-c21b75108f0e?source=rss-8851d255a5fa------2</link>
            <guid isPermaLink="false">https://medium.com/p/c21b75108f0e</guid>
            <category><![CDATA[postgres]]></category>
            <category><![CDATA[sql-server]]></category>
            <category><![CDATA[postgresql]]></category>
            <category><![CDATA[database]]></category>
            <category><![CDATA[data-engineering]]></category>
            <dc:creator><![CDATA[Mohamed Tharif]]></dc:creator>
            <pubDate>Mon, 18 May 2026 08:56:54 GMT</pubDate>
            <atom:updated>2026-05-18T08:56:54.241Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0X3sYi6QnJnctvzBFlTK_w.png" /></figure><p><strong>Architecture Overview</strong></p><p>SQL Server uses a thread-based architecture where incoming requests are converted into tasks executed by worker threads managed internally by SQL OS (SOS Scheduler). This design enables efficient multitasking, concurrency handling, and CPU utilization within a centralized engine process.</p><p>PostgreSQL uses a process-based architecture where every client connection is handled by a dedicated backend operating system process. Query execution scheduling is managed directly by the operating system scheduler rather than an internal scheduler like SQL Server.</p><p>This architectural difference is one of the most important distinctions between the two database systems and directly affects scalability, memory usage, parallelism behavior, troubleshooting, and connection management.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*y0fq__fOujjRR_3hm5tFIQ.png" /></figure><p><strong>SQL Server Architecture</strong></p><p><strong>SQL Server Execution Flow</strong></p><p><strong>SQL Server </strong>is<strong> </strong>Thread-Based Model.</p><p>SQL Server converts incoming requests into tasks and assigns worker threads from a shared thread pool. These worker threads are scheduled on CPU cores through SOS Schedulers.</p><p><strong>SQL OS and Scheduler</strong></p><p>SQL Server contains an internal operating layer called SQL OS. It manages:</p><ul><li>Worker threads</li><li>Scheduling</li><li>Memory allocation</li><li>Synchronization</li><li>I/O operations</li></ul><p>The SOS Scheduler is responsible for mapping SQL Server worker threads onto CPU cores efficiently.</p><p><strong>PostgreSQL Architecture</strong></p><p><strong>PostgreSQL Process-Based Model</strong></p><p>PostgreSQL uses a dedicated process architecture.</p><p>Each client connection creates a separate backend process at the operating system level.</p><p>Unlike SQL Server:</p><ul><li>No centralized thread pool exists</li><li>No internal scheduler similar to SOS Scheduler exists</li><li>The operating system scheduler handles process execution</li></ul><p><strong>SQL Server and PostgreSQL Request Lifecycle</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*t5_IsYgHS9t0yLr0YcH2DA.png" /></figure><p><strong>PostgreSQL Process Tree</strong></p><pre>postmaster<br>  ├── checkpointer<br>  ├── WAL writer<br>  ├── background writer<br>  ├── autovacuum launcher<br>  ├── autovacuum worker 1<br>  ├── autovacuum worker 2<br>  ├── backend_process_101<br>  ├── parallel_worker_1<br>          ├── parallel_worker_2<br>  ├── backend_process_102<br>  ├── backend_process_103<br>          ├── parallel_worker_1<br>          ├── parallel_worker_2</pre><p><strong>Shared Background Processes</strong></p><p>Even with many client connections, several PostgreSQL system processes remain singleton shared processes for the entire instance.</p><p><strong>Example</strong></p><p>500 client connections</p><p>10,000 active queries</p><p>Possible process distribution:</p><p>500 backend processes</p><p>BUT still only:</p><ul><li>1 WAL writer</li><li>1 checkpointer</li><li>1 background writer</li><li>1 autovacuum launcher</li></ul><p>Some PostgreSQL worker processes scale dynamically based on workload:</p><ul><li>Autovacuum workers</li><li>Parallel query workers</li></ul><p>Configuration parameters include:</p><ul><li>autovacuum_max_workers</li><li>max_parallel_workers</li><li>max_parallel_workers_per_gather</li></ul><p><strong>Parallelism</strong></p><p><strong>SQL Server Parallelism</strong></p><p>SQL Server parallel execution uses multiple worker threads from the shared thread pool.</p><p><strong>Parallel Thread Lifecycle</strong></p><pre>Parallel worker threads<br>↓<br>Borrowed from thread pool<br>↓<br>Execute query<br>↓<br>Returned to thread pool</pre><p><strong>Characteristics</strong></p><ul><li>Lightweight thread reuse</li><li>Lower scheduling overhead</li><li>Efficient for high concurrency</li><li>Managed internally by SQL OS</li></ul><p><strong>PostgreSQL Parallelism</strong></p><p>PostgreSQL parallel execution uses multiple operating system processes called parallel workers.</p><p><strong>Parallel Worker Lifecycle</strong></p><pre>Parallel worker processes<br>↓<br>Created temporarily<br>↓<br>Execute parallel query<br>↓<br>Terminated or released</pre><p><strong>Characteristics</strong></p><ul><li>Full operating system processes</li><li>Higher creation overhead than threads</li><li>Higher scheduling cost</li><li>Managed by operating system scheduler</li></ul><p>This is one reason PostgreSQL parallelism behaves differently from SQL Server under heavy workloads.</p><p><strong>External Command Execution</strong></p><p><strong>SQL Server xp_cmdshell Behavior</strong></p><p>SQL Server allows execution of operating system commands using xp_cmdshell.</p><p>These commands execute outside the normal SQL execution engine.</p><p>If the external operating system process hangs:</p><ul><li>The SQL Server worker thread waiting on it may also become stuck</li><li>KILL may not terminate the session successfully</li><li>The worker thread can remain blocked in external system calls</li><li>SQL Server service restart or operating system intervention may be required</li></ul><p><strong>PostgreSQL External Process Isolation</strong></p><p>PostgreSQL can face similar issues during external program execution.</p><p>However, because PostgreSQL uses isolated backend processes:</p><ul><li>Stuck operations usually affect only a single backend process</li><li>Individual backend processes are easier to terminate independently</li><li>Overall database stability is generally less affected</li></ul><p>This provides stronger isolation and fault containment compared to SQL Server.</p><p><strong>Connection Scalability</strong></p><p><strong>SQL Server</strong></p><p>SQL Server handles large connection counts efficiently because worker threads are shared through a centralized thread pool.</p><p>Memory usage per connection is relatively low.</p><p><strong>PostgreSQL</strong></p><p>PostgreSQL creates one backend process per connection.</p><p>Large numbers of connections can significantly increase:</p><ul><li>Memory usage</li><li>Process management overhead</li><li>CPU scheduling overhead</li></ul><p>For this reason, PostgreSQL environments commonly use connection pooling tools such as:</p><ul><li>PgBouncer</li><li>Pgpool-II</li></ul><p><strong>SQL Server vs PostgreSQL Internal Components</strong></p><p>Both databases implement similar core database concepts but with different internal architectures.</p><p><strong>PostgreSQL vs SQL Server</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/855/1*DpYOdmz-jARqfhnozHDIeg.png" /></figure><p><strong>Query Processing Similarities</strong></p><p>Although their architectures differ, both databases generally follow similar processing principles.</p><p><strong>General Flow</strong></p><pre>Client Query<br>↓<br>Check memory cache<br>↓<br>If data exists:<br>Return data<br>Else:<br>Read from disk<br>↓<br>Modify pages in memory<br>↓<br>Write transaction log first<br>↓<br>Checkpoint writes dirty pages to data files</pre><p>Both systems implement Write-Ahead Logging (WAL) principles to guarantee durability and crash recovery.</p><p><strong>MVCC and Concurrency Control</strong></p><p><strong>PostgreSQL MVCC</strong></p><p>PostgreSQL uses native MVCC (Multi-Version Concurrency Control).</p><p>When rows are updated or deleted:</p><ul><li>Old row versions are not immediately removed</li><li>UPDATE creates a new row version</li><li>DELETE marks rows as dead tuples</li></ul><p><strong>Important Behavior</strong></p><p>UPDATE does NOT overwrite rows in place</p><p>DELETE does NOT physically remove rows immediately</p><p>Dead tuples remain inside tables until cleaned later.</p><p><strong>Consequences of Excessive Dead Tuples</strong></p><ul><li>Table bloat</li><li>Index bloat</li><li>Slow scans</li><li>Wasted storage</li></ul><p><strong>Autovacuum</strong></p><p><strong>Purpose</strong></p><p>PostgreSQL uses Autovacuum to maintain MVCC storage efficiency.</p><p>Autovacuum does not continuously scan all tables. It triggers dynamically based on thresholds such as dead tuple counts.</p><p><strong>Components</strong></p><p><strong>Autovacuum Launcher</strong></p><p>Responsible for monitoring databases and scheduling cleanup activity.</p><p><strong>Autovacuum Workers</strong></p><p>Actual worker processes that clean dead tuples and update statistics.</p><p>The number of workers can increase dynamically depending on workload.</p><p><strong>Autovacuum Responsibilities</strong></p><p><strong>1. Vacuum</strong></p><ul><li>Cleans dead tuples</li><li>Marks space reusable</li></ul><p><strong>2. Analyze</strong></p><ul><li>Updates optimizer statistics</li><li>Helps query planner generate efficient execution plans</li></ul><p><strong>MVCC vs SQL Server Versioning</strong></p><p>PostgreSQL MVCC is conceptually similar to SQL Server row versioning, but implementation differs significantly.</p><p><strong>SQL Server</strong></p><ul><li>Primarily lock-based concurrency</li><li>Optional row versioning</li><li>Version store maintained in TempDB</li></ul><p><strong>PostgreSQL</strong></p><ul><li>Native MVCC storage engine</li><li>Every update creates new row versions</li><li>Old versions cleaned later by vacuum</li></ul><p><strong>Isolation and Concurrency</strong></p><p>PostgreSQL default isolation level is:</p><p>READ COMMITTED</p><p>Concurrency is achieved using snapshot-based MVCC, allowing:</p><ul><li>Readers and writers to operate concurrently</li><li>Reduced blocking behavior</li></ul><p><strong>Important Note</strong></p><p>MVCC continues functioning even without vacuum,</p><p>but performance eventually degrades severely.</p><p><strong>Storage Engine Differences</strong></p><p><strong>SQL Server Storage Engine</strong></p><ul><li>Page-based storage engine</li><li>In-place updates</li><li>Locking-based concurrency</li><li>Optional row versioning</li></ul><p><strong>PostgreSQL Storage Engine</strong></p><ul><li>Native MVCC storage engine</li><li>Every update creates new row versions</li><li>Vacuum-based cleanup mechanism</li></ul><p><strong>Key Architectural Differences Summary</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/855/1*7AU7m2Wb5xFAdYk7ITceBQ.png" /></figure><p><strong>Conclusion</strong></p><p>SQL Server and PostgreSQL achieve similar database goals using fundamentally different architectural approaches.</p><p>SQL Server emphasizes centralized thread scheduling, lightweight worker reuse, and integrated resource management through SQL OS.</p><p>PostgreSQL emphasizes process isolation, operating system scheduling, and native MVCC-based concurrency control.</p><p>These differences affect:</p><ul><li>Performance tuning</li><li>Connection scalability</li><li>Parallel query execution</li><li>Memory consumption</li><li>Troubleshooting behavior</li><li>Maintenance operations</li></ul><p>Understanding these architectural differences is essential when transitioning from SQL Server administration to PostgreSQL administration.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c21b75108f0e" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Migrating SQL Server 2019 to PostgreSQL 16 Using PGLoader — Experience, Issues, and Limitations]]></title>
            <link>https://medium.com/@mohammedtharif30/migrating-sql-server-2019-to-postgresql-16-using-pgloader-experience-issues-and-limitations-364bbd331ab4?source=rss-8851d255a5fa------2</link>
            <guid isPermaLink="false">https://medium.com/p/364bbd331ab4</guid>
            <category><![CDATA[pgloader]]></category>
            <category><![CDATA[mssql]]></category>
            <category><![CDATA[database-migration]]></category>
            <category><![CDATA[postgres]]></category>
            <category><![CDATA[sql-server]]></category>
            <dc:creator><![CDATA[Mohamed Tharif]]></dc:creator>
            <pubDate>Thu, 07 May 2026 18:33:45 GMT</pubDate>
            <atom:updated>2026-05-07T18:33:45.436Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*d55PBNxo3uALMhmIb39dtw.jpeg" /></figure><p>Recently, I worked on a Proof of Concept (POC) for migrating Microsoft SQL Server 2019 to PostgreSQL 16.</p><p>For the initial migration approach, I chose pgloader because it is relatively easy to set up and provides direct support for SQL Server to PostgreSQL migration.</p><p>At the beginning, pgloader looked like a very good option for the migration. However, once the migration started moving closer to a production-grade setup, several limitations and failures became visible. I experienced multiple issues while testing with the AdventureWorks 2019 database.</p><p>In this blog, I will cover:</p><ul><li>Environment setup</li><li>Migration approach</li><li>Problems faced during migration</li><li>Fixes and workarounds</li><li>Practical limitations of pgloader</li><li>Alternative considerations for complex migrations</li></ul><p><strong>Environment Setup</strong></p><p>I built two separate virtual machines for the migration setup.</p><p><strong>Windows VM</strong></p><p>Used as the source database server.</p><p>Setup included:</p><ul><li>SQL Server 2019 Developer Edition</li><li>AdventureWorks2019 database restored</li><li>Separate login created for migration user</li><li>TCP/IP enabled in SQL Server Configuration Manager</li><li>Windows firewall and network configuration updated to allow Ubuntu VM access and pgloader connectivity</li></ul><p><strong>Ubuntu VM</strong></p><p>Used as the <a href="https://github.com/MohamedTharif/Postgresql-to-SQL-Server-Migration/blob/main/Postgre%20Sql%20Setup%20Guide%20(ubuntu%20On%20Vmware).pdf">PostgreSQL</a> and migration server.</p><p>Setup included:</p><ul><li>Ubuntu Server</li><li>Network configuration using DHCP</li><li>SSH configuration</li><li>PostgreSQL 16 installation</li><li>pgloader installation</li><li>Python and pyodbc installed for connectivity testing</li><li>PostgreSQL database created for migration</li></ul><p>Personally, Linux environments always feel easier and cleaner to work with for database and migration-related activities.</p><p>Installation and setup documentation for both environments are attached in the reference link.</p><p><strong>Prerequisites Before Migration</strong></p><p>Before starting the migration, several configurations were required.</p><p><strong>FreeTDS Configuration</strong></p><p>When loading data from SQL Server, pgloader depends on FreeTDS.</p><p>I had to configure the ~/.freetds.conf file as follows:</p><pre>[global]<br> tds version = 7.4<br> client charset = UTF-8<br> min pool conn = 20<br> max pool conn = 8192<br> max member age = 120</pre><p>Without this configuration, pgloader continuously failed with:</p><p>Max connections reached, increase value of TDS_MAX_CONN</p><p>In several cases, pgloader crashed completely and dropped into the Lisp debugger.</p><p><strong>PostgreSQL Compatibility and Collation</strong></p><p>The PostgreSQL database needs to be created carefully with matching compatibility expectations and collation settings.</p><p>Collation differences between SQL Server and PostgreSQL can lead to unexpected behavior after migration.</p><pre>--SQL Server Database Collation<br>SELECT<br>    name,<br>    collation_name<br>FROM sys.databases<br>WHERE name = &#39;AdventureWorks2019&#39;;<br><br>--Postgres Database Collation<br>SELECT<br>    datname,<br>    encoding,<br>    datcollate,<br>    datctype<br>FROM pg_database<br>WHERE datname = &#39;testdb&#39;;</pre><p><strong>UUID Extension</strong></p><p>UUID support was required in PostgreSQL and needed to be enabled manually before migration.</p><pre>CREATE EXTENSION &quot;uuid-ossp&quot;;</pre><p><strong>Authentication Issues</strong></p><p>Authentication failures occurred because of PostgreSQL password encryption policies.</p><p>The postgresql.conf file needed verification and adjustment based on the pgloader compatibility.</p><p><strong>Network Accessibility</strong></p><p>Connectivity between both virtual machines must be validated before starting migration:</p><ul><li>SQL Server port accessibility</li><li>PostgreSQL accessibility</li><li>SSH connectivity</li><li>Firewall rules</li><li>DNS/IP resolution</li></ul><p><strong>Migration Approach Using PGLoader</strong></p><p>The migration was planned as a two-phase approach.</p><p><strong>Phase 1 — Schema Only Migration</strong></p><p><strong>Phase 2 — Data Only Migration</strong></p><p>This approach helped isolate schema conversion problems from data movement issues.</p><p><a href="https://github.com/MohamedTharif/Postgresql-to-SQL-Server-Migration/blob/main/Phase%201.pdf"><strong>Phase 1 — Schema Migration</strong></a></p><p>pgloader supports schema-only migration without loading data.</p><p>pgloader works very well for:</p><ul><li>Normal tables</li><li>Primary keys</li><li>Standard indexes</li><li>Regular datatypes</li><li>Bulk loading operations</li></ul><p>However, SQL Server contains many proprietary features that PostgreSQL does not support directly, and pgloader cannot fully translate all SQL Server semantics automatically.</p><p><strong>Problems Faced During Schema Migration</strong></p><p><strong>Computed Columns</strong></p><p>Computed columns from SQL Server were not migrated correctly.</p><p>Instead of preserving the logic, pgloader converted them into plain text columns.</p><p>The computed logic had to be recreated manually in PostgreSQL.</p><p><strong>Foreign Keys and Composite Keys</strong></p><p>PostgreSQL requires referenced columns in foreign keys to be either:</p><ul><li>Primary keys</li><li>Unique keys</li></ul><p>SQL Server is more flexible in some scenarios.</p><p>The existing schema design in AdventureWorks2019 did not always satisfy PostgreSQL requirements.</p><p>Because of this:</p><ul><li>Some foreign keys could not be created directly</li><li>Tables had to be migrated first without constraints</li><li>Foreign keys were added later manually</li></ul><p>However, this created another issue during Phase 2.</p><p>If orphan records existed in child tables, referential integrity validation failed while creating constraints later.</p><p><strong>Index Creation Issues</strong></p><p>Some SQL Server indexes could not be migrated properly.</p><p>Problems included:</p><ul><li>XML indexes</li><li>SQL Server-specific indexing behavior</li><li>Unsupported index structures</li></ul><p>PostgreSQL XML indexing does not behave the same way as SQL Server XML indexes.</p><p>In many cases, the best approach was:</p><ol><li>Skip index creation during migration</li><li>Validate schema and data</li><li>Recreate indexes manually afterward</li></ol><p><strong>Naming Convention Limitations</strong></p><p>PostgreSQL allows only 63 characters for object names.</p><p>SQL Server supports up to 128 characters.</p><p>Several objects required renaming because names exceeded PostgreSQL limits.</p><p><strong>Unsupported Proprietary Datatypes</strong></p><p>One of the major blockers was proprietary SQL Server datatypes.</p><p>Examples included:</p><ul><li>SYBMSXML</li><li>SYBMSUDT</li><li>CLR types</li><li>hierarchyid</li><li>geography</li><li>geometry</li></ul><p>pgloader generated errors such as:</p><p>unsupported type SYB-MSUDT</p><p>These errors originated from FreeTDS and pgloader while reading SQL Server metadata.</p><p>Because of these unsupported datatypes:</p><ul><li>Metadata extraction failed</li><li>Row conversion failed</li><li>Parser crashes occurred</li><li>Runtime instability increased significantly</li></ul><p><strong>Phase 2 — Data Migration</strong></p><p>This phase introduced even more stability and datatype-related issues.</p><p><strong>Problems Faced During Data Migration</strong></p><p><strong>Unsupported Datatype Failures</strong></p><p>Data movement failed for tables containing unsupported datatypes like SYB-MSUDT.</p><p>The failure pattern was:</p><ul><li>pgloader encounters unsupported type</li><li>Conversion process fails</li><li>FreeTDS cleanup breaks</li><li>SBCL runtime crashes</li></ul><p><strong>Runtime Failures During Full Database Migration</strong></p><p>Migrating the complete database in a single run was not feasible.</p><p>pgloader internally uses:</p><ul><li>SBCL (Lisp runtime)</li><li>FreeTDS (SQL Server driver)</li></ul><p>Error handling becomes unstable when:</p><ul><li>Unsupported datatypes are encountered</li><li>Connections fail unexpectedly</li><li>Cleanup operations break</li></ul><p>Large database migrations with complex schemas caused runtime crashes repeatedly.</p><p><strong>Switching to Table-Level Migration</strong></p><p>Since full database migration failed continuously, I changed the strategy to table-level migration.</p><p>The loading sequence followed:</p><ol><li>Lookup and master tables</li><li>Parent tables</li><li>Child tables</li><li>Transaction tables</li></ol><p>This improved control over migration dependencies.</p><p>However, tables containing:</p><ul><li>hierarchyid</li><li>geometry</li><li>geography</li><li>Complex CLR types</li></ul><p>still failed consistently because pgloader could not deserialize these datatypes correctly.</p><p><strong>Final Outcome of the POC</strong></p><p>The migration succeeded for:</p><ul><li>Tables with simpler datatypes</li><li>Standard relational structures</li><li>Simpler relationships</li></ul><p>However, tables containing:</p><ul><li>Proprietary SQL Server datatypes</li><li>Spatial types</li><li>Complex relationships</li><li>Advanced SQL Server-specific features</li></ul><p>required:</p><ul><li>Custom ETL solutions</li><li>Manual schema recreation</li><li>Alternative migration tools</li></ul><p>Additionally:</p><ul><li>Foreign keys were created manually</li><li>Indexes were recreated manually</li><li>Constraint validation required manual verification</li></ul><p><strong>Conclusion</strong></p><p>pgloader is a very good tool for:</p><ul><li>Small to medium migrations</li><li>Standard relational databases</li><li>Simple schema structures</li><li>Quick POCs</li></ul><p>But for production-grade SQL Server migrations involving:</p><ul><li>Proprietary SQL Server features</li><li>Spatial datatypes</li><li>CLR types</li><li>Complex relational dependencies</li><li>Enterprise-scale databases</li></ul><p>pgloader alone may not be sufficient.</p><p>A hybrid migration strategy involving:</p><ul><li>Manual schema adjustments</li><li>Custom ETL pipelines</li><li>Alternative migration utilities</li><li>Incremental table-level migration</li></ul><p>becomes necessary for stable migration execution.</p><p><a href="https://github.com/MohamedTharif/Postgresql-to-SQL-Server-Migration">GitHub</a> repository containing migration scripts, setup documentation, configuration files, and troubleshooting references used during the SQL Server 2019 to PostgreSQL 16 migration POC.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=364bbd331ab4" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Disaster Recovery in MSSQL: Overview & Strategies]]></title>
            <link>https://medium.com/@mohammedtharif30/disaster-recovery-in-mssql-overview-strategies-7c74dde428cc?source=rss-8851d255a5fa------2</link>
            <guid isPermaLink="false">https://medium.com/p/7c74dde428cc</guid>
            <category><![CDATA[mirroring]]></category>
            <category><![CDATA[ms-sql-server]]></category>
            <category><![CDATA[log-shipping]]></category>
            <category><![CDATA[sql]]></category>
            <category><![CDATA[dr-strategy]]></category>
            <dc:creator><![CDATA[Mohamed Tharif]]></dc:creator>
            <pubDate>Tue, 25 Mar 2025 16:33:33 GMT</pubDate>
            <atom:updated>2025-03-25T16:33:33.972Z</atom:updated>
            <content:encoded><![CDATA[<p><strong>Introduction</strong></p><p>Disaster Recovery (DR) in Microsoft SQL Server is a crucial process for ensuring business continuity and minimizing data loss in the event of hardware failures, cyber-attacks, system crashes, or natural disasters. A well-defined DR strategy ensures that databases remain available with minimal downtime. SQL Server provides multiple recovery options, each with different levels of Recovery Point Objective (RPO) and Recovery Time Objective (RTO).</p><p><strong>Why Disaster Recovery is Important</strong></p><ul><li>Ensures business continuity</li><li>Reduces downtime and data loss</li><li>Protects against cyber threats and accidental deletions</li><li>Meets compliance and regulatory requirements</li></ul><p><strong>Key Disaster Recovery Strategies in MSSQL</strong></p><p><strong>1. Backup and Restore(</strong><a href="https://medium.com/@mohammedtharif30/backup-and-recovery-in-mssql-rto-rpo-and-backup-strategies-ba9b58807275"><strong><em>For detailed implementation, refer to Backup and Restore Guide</em></strong></a><strong>)</strong></p><p>The foundation of any DR plan is a reliable backup and restore strategy. SQL Server supports multiple backup types:</p><ul><li><strong>Full Backup</strong>: Captures the entire database.</li><li><strong>Differential Backup</strong>: Backs up changes since the last full backup.</li><li><strong>Transaction Log Backup</strong>: Captures transactional changes, enabling point-in-time recovery.</li></ul><p><strong>2. Log Shipping <em>(</em></strong><a href="https://medium.com/@mohammedtharif30/deep-dive-into-log-shipping-in-mssql-79e411fb46dc"><strong><em>For detailed implementation, refer to Log Shipping Guide</em></strong></a><strong><em>)</em></strong></p><p>Log Shipping automatically copies and restores transaction logs from a primary server to one or more secondary servers. It provides a warm standby solution with some delay in synchronization.</p><p><strong>Key Features:</strong></p><ul><li>Automates transaction log backups and restores</li><li>Supports multiple secondary servers</li><li>Provides disaster recovery with minimal complexity</li></ul><p><strong>3. Database Mirroring <em>(</em></strong><a href="https://medium.com/@mohammedtharif30/sql-server-database-mirroring-high-availability-and-disaster-recovery-explained-4ef4839431e4"><strong><em>For detailed implementation, refer to Mirroring Guide</em></strong></a><strong><em>)</em></strong></p><p>Database Mirroring maintains a real-time copy of a database on a secondary server, providing high availability and disaster recovery.</p><p><strong>Modes of Operation:</strong></p><ul><li><strong>Synchronous (High-Safety Mode)</strong>: Ensures zero data loss but may introduce latency.</li><li><strong>Asynchronous (High-Performance Mode)</strong>: Provides better performance with a risk of minimal data loss.</li></ul><p><strong>4. Always On Availability Groups</strong></p><p>Always On Availability Groups (AGs) provide advanced disaster recovery and high availability by supporting multiple readable secondary replicas.</p><p><strong>Key Benefits:</strong></p><ul><li>Allows automatic and manual failover</li><li>Enables read-only queries on secondary replicas</li><li>Offers near-zero data loss with synchronous replication</li></ul><p><strong>5. Replication</strong></p><p>Replication involves copying and distributing database objects from one server to another, keeping them in sync. It is mainly used for data distribution and reporting.</p><p><strong>Types of Replication:</strong></p><ul><li><strong>Snapshot Replication</strong>: Transfers a static copy of the database.</li><li><strong>Transactional Replication</strong>: Continuously replicates changes in near real-time.</li><li><strong>Merge Replication</strong>: Allows updates on both primary and secondary databases.</li></ul><p><strong>6. Failover Clustering</strong></p><p>SQL Server Failover Cluster Instances (FCI) provide high availability by grouping multiple servers into a cluster. If one node fails, another takes over, ensuring continuous availability.</p><p><strong>Choosing the Right Disaster Recovery Strategy</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/795/1*8jzs-crolp3S10iJ42RT_w.png" /><figcaption>Comparison of the different Strategies</figcaption></figure><p><strong>Conclusion</strong></p><p>Disaster Recovery in MSSQL is essential for protecting business-critical data. The right strategy depends on business requirements, system architecture, and tolerance for downtime and data loss. While <strong>backup and restore</strong> is the most fundamental approach, <strong>log shipping, mirroring, Always On, and failover clustering</strong> provide advanced solutions for minimizing downtime and ensuring data integrity.</p><p><strong>For detailed guides on implementing specific disaster recovery methods, refer to:</strong></p><ul><li><a href="https://medium.com/@mohammedtharif30/deep-dive-into-log-shipping-in-mssql-79e411fb46dc">Log Shipping Guide</a></li><li><a href="https://medium.com/@mohammedtharif30/sql-server-database-mirroring-high-availability-and-disaster-recovery-explained-4ef4839431e4">Mirroring Guide</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7c74dde428cc" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[“SQL Server Database Mirroring: High Availability and Disaster Recovery Explained”]]></title>
            <link>https://medium.com/@mohammedtharif30/sql-server-database-mirroring-high-availability-and-disaster-recovery-explained-4ef4839431e4?source=rss-8851d255a5fa------2</link>
            <guid isPermaLink="false">https://medium.com/p/4ef4839431e4</guid>
            <category><![CDATA[backup]]></category>
            <category><![CDATA[mssql-server]]></category>
            <category><![CDATA[sql-server]]></category>
            <category><![CDATA[mssql]]></category>
            <category><![CDATA[mirroring]]></category>
            <dc:creator><![CDATA[Mohamed Tharif]]></dc:creator>
            <pubDate>Tue, 25 Mar 2025 13:31:42 GMT</pubDate>
            <atom:updated>2025-03-25T16:07:26.819Z</atom:updated>
            <content:encoded><![CDATA[<h3><strong>“SQL Server Mirroring: High Availability and Disaster Recovery Explained”</strong></h3><p><strong>Introduction</strong></p><p>SQL Server mirroring maintains two copies of a single database on separate server instances of the SQL Server Database Engine. This technology enhances high availability by keeping a synchronized copy of the primary (principal) database on a secondary (mirror) server and offers both manual and automatic failover options. As a disaster recovery strategy, mirroring minimizes downtime and data loss by ensuring that if the primary server fails, the mirror is ready to take over immediately.</p><p><strong>Prerequisites</strong></p><p><strong>Understanding Backups and Log Shipping</strong></p><p>Before setting up mirroring, it’s important to understand:</p><ul><li><strong>Backups:</strong> Regular full, differential, and transaction log backups secure your data and are part of a broader disaster recovery strategy.</li><li><strong>Log Shipping:</strong> Automatically sends transaction log backups from one server (primary) to another (secondary) to maintain an up-to-date copy of the database.</li><li>For more details about Log Shipping <a href="https://medium.com/@mohammedtharif30/deep-dive-into-log-shipping-in-mssql-79e411fb46dc">https://medium.com/@mohammedtharif30/deep-dive-into-log-shipping-in-mssql-79e411fb46dc</a></li></ul><p><strong>Why It Is Needed</strong></p><ul><li><strong>Minimize Downtime:</strong> Allows for a quick switch to the mirror if the primary fails.</li><li><strong>Ensure Data Consistency:</strong> Synchronizes transactions in real time, keeping data consistent across servers.</li><li><strong>High Availability:</strong> Supports critical applications that require continuous uptime.</li></ul><p><strong>What is Mirroring?</strong></p><p>Mirroring is a high-availability solution that creates and maintains two copies of a database:</p><ul><li><strong>Principal Server:</strong> The primary server connected to clients where all transactions are initiated.</li><li><strong>Mirror Server:</strong> A secondary server that continuously receives and applies changes from the principal.</li><li><strong>Witness Server (Optional):</strong> Monitors the connection between the principal and mirror and helps trigger automatic failover if needed.</li></ul><p><strong><em>Note: Mirroring requires the database to use the Full Recovery Model.</em></strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/741/1*Z8ogMAxA-PlGPD7aFmub9w.png" /><figcaption>Mirroring Architecture</figcaption></figure><p><strong>Log Shipping vs. Mirroring</strong></p><p><strong>Log shipping</strong> copies transaction logs at regular intervals from a primary server to a secondary server, providing a backup that is slightly delayed. <strong>Mirroring</strong> continuously synchronizes a secondary server with the primary, offering a near real-time duplicate for quick failover.</p><p><strong>Real-World Example</strong></p><p>Imagine an online store:</p><ul><li>They use <strong>mirroring</strong> for their order processing system to ensure immediate failover if the primary server fails, keeping transactions live.</li><li>They use <strong>log shipping</strong> for their reporting system, updating data every few minutes so the analytics team can generate reports without impacting the live environment.</li></ul><p><strong>Components for the Mirroring</strong></p><p><strong>Principal Server</strong></p><ul><li>Hosts the primary database.</li><li>Processes client transactions and writes transaction logs.</li></ul><p><strong>Mirror Server</strong></p><ul><li>Maintains a near real-time copy of the principal database.</li><li>Receives and applies committed transaction logs via dedicated TCP endpoints.</li></ul><p><strong>Witness Server (Optional)</strong></p><ul><li>Monitors the status of the principal.</li><li>Participates in a voting process to trigger automatic failover when necessary.</li></ul><p><strong>How it Works</strong></p><p><strong>What is Failover?</strong></p><p>Failover is the process of switching operations from a primary database server to a standby server when the primary becomes unavailable. This ensures that applications continue to operate with minimal interruption and data loss.</p><p><strong>Failover: Automatic vs. Manual</strong></p><ul><li><strong>Manual Failover:</strong></li><li>Requires only the principal and mirror.</li><li>An administrator manually reassigns roles, resulting in a period of downtime.</li><li><strong>Automatic Failover:</strong></li><li>Involves the principal, mirror, and witness servers.</li><li>Heartbeat signals from all three servers determine availability. If the witness loses connection to the primary, the mirror is automatically promoted to primary, minimizing downtime.</li><li><strong><em>Note: If the principal loses connection to the mirror but remains connected to the witness, automatic failover does not occur.</em></strong></li></ul><p>There are two primary operational modes in SQL Server mirroring, each offering different trade-offs between safety and performance:</p><ul><li><strong>Synchronous Mode (High-Safety):</strong><br> Ensures that every transaction is committed on both the principal and mirror before confirming the commit to the client. This mode maximizes data protection by fully synchronizing both servers, albeit at a potential performance cost.</li><li><strong>Asynchronous Mode (High-Performance):</strong><br> Prioritizes transaction speed by confirming commits on the principal immediately. The transaction log is sent to the mirror after the fact, which may lead to a slight lag in synchronization but boosts overall performance.</li></ul><p><strong>Example Scenario for the Synchronous and Asynchronous modes:</strong></p><p><strong>Synchronous Mode (High-Safety)</strong></p><ol><li>A client initiates a transaction on the principal.</li><li>The principal writes the transaction to its local log.</li><li>The transaction log is sent immediately to the mirror.</li><li>The mirror writes the log record to its own log and sends an acknowledgment.</li><li>Once the acknowledgment is received, the principal confirms the commit to the client.</li></ol><p><strong>Result</strong>: The transaction is committed on both servers before confirmation, ensuring full synchronization.</p><p><strong>Asynchronous Mode (High-Performance)</strong></p><ol><li>A client initiates a transaction on the principal.</li><li>The principal writes the transaction to its log and immediately confirms the commit to the client.</li><li>The transaction log is sent to the mirror after the commit.</li><li>The mirror applies the transaction later, which may introduce a slight delay.</li></ol><p><strong>Result</strong>: Improved performance with a potential minor lag on the mirror.</p><p><strong><em>Note: Automatic failover in SQL Server mirroring is supported only when operating in synchronous (high-safety) mode with a witness server configured. Manual failover, on the other hand, can be initiated in both synchronous and asynchronous modes.</em></strong></p><p><strong>Implementation Using TCP Endpoints</strong></p><p>Mirroring uses dedicated TCP endpoints to transfer transaction logs between the principal and mirror servers. This section shows how to configure these endpoints using T‑SQL, and notes that a GUI method (via SQL Server Management Studio) is also available.</p><p>There are two ways to set up SQL Server instances for mirroring:</p><ol><li><strong>Creating Two Instances on a Single Machine</strong> — This method involves installing multiple SQL Server instances on the same machine. It is useful for testing and development purposes.</li><li><strong>Creating Two Instances Under a Domain in a Server</strong> — This approach is used in enterprise environments where SQL Server instances are installed on different machines within a domain, allowing authentication and communication using domain accounts.</li></ol><p><strong>Using T‑SQL Commands</strong></p><p><strong>Create Mirroring Endpoints on Principal and Mirror Servers</strong></p><p><strong>On the Principal Server:</strong></p><pre>— Create the mirroring endpoint on the Principal Server<br>CREATE ENDPOINT [Mirroring]<br>STATE = STARTED<br>AS TCP (LISTENER_PORT = 5022)<br>FOR DATA_MIRRORING (ROLE = ALL);<br>- Grant connect permission to the public role<br>GRANT CONNECT ON ENDPOINT::[Mirroring] TO PUBLIC;</pre><p><strong>On the Mirror Server:</strong></p><pre> — <br>CREATE ENDPOINT [Mirroring]<br>STATE = STARTED<br>AS TCP (LISTENER_PORT = 5022)<br>FOR DATA_MIRRORING (ROLE = ALL);<br> - Grant connect permission to the public role<br>GRANT CONNECT ON ENDPOINT::[Mirroring] TO PUBLIC;</pre><p><strong>Configuring the Database for Mirroring</strong></p><p><strong>On the Principal Server:</strong></p><pre>- Configure the database to set up mirroring<br>ALTER DATABASE YourDatabase<br>SET PARTNER = &#39;TCP://MirrorServer:5022&#39;;<br> - (Optional) Configure the witness server for automatic failover<br>ALTER DATABASE YourDatabase<br>SET WITNESS = &#39;TCP://WitnessServer:5022&#39;;</pre><p><strong>Verifying the Mirroring Configuration</strong></p><pre>SELECT<br>DB_NAME(database_id) AS DatabaseName,<br>mirroring_state_desc,<br>mirroring_partner_name,<br>mirroring_witness_name<br>FROM sys.database_mirroring<br>WHERE DB_NAME(database_id) = &#39;YourDatabase&#39;;</pre><p><strong>Using the GUI (SQL Server Management Studio)</strong></p><p>Alternatively, you can configure mirroring via SSMS:</p><ol><li>Open SSMS and connect to your SQL instance.</li><li>Right-click on the database → select <strong>Properties</strong>.</li><li>Navigate to the <strong>Mirroring</strong> page and follow the wizard to configure the principal, mirror, and (optional) witness servers.</li><li>Provide the TCP endpoint details for each server and complete the configuration.</li></ol><p><strong>Database Snapshots and Standby Mode</strong></p><p><strong>Database Snapshots</strong></p><p><strong>Purpose:</strong></p><p>Since a mirrored database is in standby (or no recovery) mode and cannot be directly accessed, database snapshots provide a read-only view for reporting or analysis.</p><p><strong>Use Cases:</strong></p><ul><li><strong>Reporting and Analytics:</strong> Enables DBAs or developers to query current data without interfering with the mirroring process.</li><li><strong>Historical Analysis:</strong> Offers point-in-time copies to analyze changes over time.</li><li><strong>How It Works:</strong><br> Snapshots capture the actual data pages at a moment in time, stored separately from the live mirrored database.</li></ul><p><strong>Standby Mode</strong></p><p>In standby mode, the mirror database is continuously updated yet remains inaccessible to clients. Database snapshots allow read operations on a stable, historical view of the data without disrupting ongoing mirroring.</p><p><strong>Conclusion</strong></p><p>SQL Server mirroring is a powerful solution for ensuring high availability and data integrity. By using dedicated TCP endpoints and choosing between synchronous (high-safety) and asynchronous (high-performance) modes, organizations can minimize downtime and data loss. Whether configured via T‑SQL or the SSMS GUI, mirroring — with components such as the principal, mirror, and optional witness servers — ensures continuous data protection. Additionally, database snapshots enable access to read-only data for reporting and analysis, even while the mirrored database remains in standby mode.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4ef4839431e4" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Backup and Recovery in MSSQL:RTO, RPO, and Backup Strategies.]]></title>
            <link>https://medium.com/@mohammedtharif30/backup-and-recovery-in-mssql-rto-rpo-and-backup-strategies-ba9b58807275?source=rss-8851d255a5fa------2</link>
            <guid isPermaLink="false">https://medium.com/p/ba9b58807275</guid>
            <category><![CDATA[sql]]></category>
            <category><![CDATA[backup]]></category>
            <category><![CDATA[disaster-recovery]]></category>
            <category><![CDATA[sql-server]]></category>
            <category><![CDATA[ms-sql-server]]></category>
            <dc:creator><![CDATA[Mohamed Tharif]]></dc:creator>
            <pubDate>Mon, 24 Mar 2025 18:21:10 GMT</pubDate>
            <atom:updated>2025-03-24T18:24:32.602Z</atom:updated>
            <content:encoded><![CDATA[<p>We are going to discuss database backups, which are essential for ensuring high availability and disaster recovery in SQL Server. A well-planned backup strategy helps protect against data loss, system failures, and accidental deletions, ensuring business continuity. This guide covers different types of backups, recovery models, and best practices for maintaining a reliable backup and restore process in MSSQL.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/300/1*u4RLxRPYfVewmXP26D5HqQ.png" /><figcaption>Backup and Restore</figcaption></figure><p><strong>1. Understanding Backup in MSSQL</strong></p><p>Backup in MSSQL is essential for disaster recovery, minimizing downtime and data loss. Two key recovery objectives define an effective backup strategy:</p><ul><li><strong>Recovery Time Objective (RTO):</strong> Maximum downtime allowed after a disaster.</li><li><strong>Recovery Point Objective (RPO):</strong> Maximum acceptable data loss in case of failure.</li></ul><p><strong>2. Types of Backups in MSSQL</strong></p><p><strong>2.1 Recovery Models</strong></p><p>MSSQL offers three recovery models that determine how backups are managed:</p><ul><li><strong>Simple Recovery Model</strong> — No log backups; minimal storage usage.</li><li><strong>Full Recovery Model</strong> — Requires log backups; ensures point-in-time recovery.</li><li><strong>Bulk-Logged Recovery Model</strong> — Reduces log size for bulk operations but still allows point-in-time recovery.</li></ul><p><strong>2.2 Backup Types</strong></p><p>MSSQL provides different types of backups for various scenarios:</p><ul><li><strong>Full Backup</strong> — Backs up the entire database, including logs.</li><li><strong>Differential Backup</strong> — Captures only changes made since the last full backup.</li><li><strong>Transaction Log (T-Log) Backup</strong> — Backs up transaction logs for point-in-time recovery.</li><li><strong>Tail-Log Backup</strong> — Captures the active portion of the transaction log before restoring or recovering a database to prevent data loss.</li></ul><p><strong>2.3 Backup File Formats</strong></p><ul><li><strong>.bak</strong> → Used for full and differential database backups.</li><li><strong>.trn</strong> → Used for transaction log backups.</li><li><strong>.diff</strong> → Sometimes used for differential backups.</li></ul><p><strong>2.4 Backup Strategy Example</strong></p><ul><li><strong>Full Backup</strong> — Daily or Weekly (as per RPO)</li><li><strong>Differential Backup</strong> — 4hours or Daily (as per RPO)</li><li><strong>T-Log Backup</strong> — Every 10–15 minutes (as per RPO)</li></ul><p><strong>3. Example Scenario: Backup Schedule in a Day</strong></p><p>Consider a real-time System with frequent transactions.</p><p>A well-structured backup schedule ensures minimal data loss and efficient recovery. Below is an example of a database backup plan throughout a working day:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/647/1*NkyACEDpec1OAzqTarUo3g.png" /><figcaption>Example Backup schedule</figcaption></figure><p>This backup schedule ensures:</p><ul><li><strong>Full backup</strong> provides a complete recovery point.</li><li><strong>Differential backups</strong> track changes after the full backup, reducing restore time.</li><li><strong>T-Log backups</strong> allow point-in-time recovery in case of failure.</li></ul><p><strong>4. Ways to Implement Backup and Restore</strong></p><p><strong>4.1 Using T-SQL</strong></p><p><strong>Setting Recovery Model</strong></p><pre>SELECT name, recovery_model_desc FROM sys.databases WHERE name = &#39;YourDatabase&#39;;<br>ALTER DATABASE YourDatabase SET RECOVERY FULL;<br>Performing Backups</pre><p><strong>Performing Backups</strong></p><p><strong>Full Backup (Overwrite existing backup)</strong></p><pre>BACKUP DATABASE YourDatabase <br>TO DISK = &#39;C:\Backups\YourDatabase_Full.bak&#39; <br>WITH INIT, COMPRESSION, STATS = 10;</pre><p><strong>Differential Backup</strong></p><pre>BACKUP DATABASE YourDatabase <br>TO DISK = &#39;C:\Backups\YourDatabase_Diff.bak&#39; <br>WITH DIFFERENTIAL, COMPRESSION, STATS = 10;</pre><p><strong>T-Log Backup</strong></p><pre>BACKUP LOG YourDatabase  <br>TO DISK = &#39;C:\Backups\YourDatabase_TailLog.trn&#39;  <br>WITH NORECOVERY, STATS = 10;</pre><p><strong>Performing a Tail-Log Backup</strong></p><p>A <strong>Tail-Log Backup</strong> is used when the database is damaged, but you need to back up the transaction log before performing a restore. This ensures no transactions are lost.</p><pre>BACKUP LOG YourDatabase  <br>TO DISK = &#39;C:\Backups\YourDatabase_TailLog.trn&#39;  <br>WITH NORECOVERY, STATS = 10;</pre><h3>Restoring Backups</h3><p><strong>Restore Full Backup</strong></p><pre>RESTORE DATABASE YourDatabase <br>FROM DISK = &#39;C:\Backups\YourDatabase_Full.bak&#39; <br>WITH NORECOVERY, STATS = 10;</pre><p><strong>Restore Differential Backup</strong></p><pre>RESTORE DATABASE YourDatabase <br>FROM DISK = &#39;C:\Backups\YourDatabase_Diff.bak&#39; <br>WITH RECOVERY, STATS = 10;</pre><p><strong>Restore T-Log Backup</strong></p><pre>RESTORE LOG YourDatabase <br>FROM DISK = &#39;C:\Backups\YourDatabase_Log.trn&#39; <br>WITH STOPAT = &#39;2024-02-27 15:30:00&#39;, RECOVERY, STATS = 10;</pre><p><strong>Restore Tail-Log Backup Before Recovery</strong></p><pre>RESTORE LOG YourDatabase  <br>FROM DISK = &#39;C:\Backups\YourDatabase_TailLog.trn&#39;  <br>WITH NORECOVERY, STATS = 10;</pre><p><strong>4.2 Backup Using GUI (SQL Server Management Studio — SSMS)</strong></p><ol><li>Open SSMS and connect to the SQL instance.</li><li>Right-click the database → Select <strong>Tasks</strong> → <strong>Back Up…</strong></li><li>Choose <strong>Backup Type</strong> (Full, Differential, or Transaction Log).</li><li>Specify the destination path.</li><li>Click <strong>OK</strong> to start the backup.</li></ol><p><strong>4.3 Automating Backups with SQL Server Agent (Maintenance Plan)</strong></p><ul><li><strong>Using SQL Server Agent</strong></li></ul><ol><li>Ensure <strong>SQL Server Agent</strong> is running.</li><li>In SSMS, navigate to <strong>SQL Server Agent → Jobs</strong>.</li><li>Right-click and select <strong>New Job</strong> → Configure the backup command.</li></ol><ul><li><strong>Using Maintenance Plans</strong></li></ul><ol><li>Go to <strong>Management → Maintenance Plans</strong> in SSMS.</li><li>Create a <strong>New Maintenance Plan</strong>.</li><li>Add a <strong>Back Up Database Task</strong> and configure it with schedule settings.</li></ol><p><strong>5. Copy-Only Backup (Non-Disruptive Backup)</strong></p><p>A <strong>Copy-Only Backup</strong> creates a backup without affecting the existing backup chain.</p><pre>BACKUP DATABASE YourDatabase<br>TO DISK = &#39;C:\Backups\YourDatabase_CopyOnly.bak&#39;<br>WITH COPY_ONLY, COMPRESSION, STATS = 10;</pre><p><strong>Conclusion</strong></p><p>Understanding <strong>RTO, RPO</strong>, and <strong>backup strategies</strong> is critical for database recovery. By implementing the right combination of <strong>full, differential, T-log, and tail-log backups</strong>, along with <strong>automated maintenance plans</strong>, you can minimize downtime and data loss effectively in MSSQL.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ba9b58807275" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Deep Dive into Log Shipping in MSSQL]]></title>
            <link>https://medium.com/@mohammedtharif30/deep-dive-into-log-shipping-in-mssql-79e411fb46dc?source=rss-8851d255a5fa------2</link>
            <guid isPermaLink="false">https://medium.com/p/79e411fb46dc</guid>
            <category><![CDATA[disaster-recovery]]></category>
            <category><![CDATA[mssql]]></category>
            <category><![CDATA[backup]]></category>
            <category><![CDATA[sql-server]]></category>
            <category><![CDATA[log-sh]]></category>
            <dc:creator><![CDATA[Mohamed Tharif]]></dc:creator>
            <pubDate>Thu, 20 Mar 2025 07:20:39 GMT</pubDate>
            <atom:updated>2025-03-20T07:24:39.113Z</atom:updated>
            <content:encoded><![CDATA[<h3><strong>Prerequisites</strong></h3><p>Before setting up Log Shipping, it’s important to understand the key backup and restore concepts:</p><ul><li><strong>Full Backup</strong>: A complete backup of the database, used as the baseline for recovery.</li><li><strong>Transaction Log Backup (T-Log Backup)</strong>: Captures all transactions that have occurred since the last transaction log backup.</li><li><strong>Tail-Log Backup</strong>: Ensures that all uncommitted transactions are captured before a restore operation.</li></ul><p><strong>Why Log Shipping?</strong></p><p>Database availability is crucial for business continuity. If a disaster occurs (e.g., hardware failure, software crash, or data corruption), you need a reliable disaster recovery strategy. Two common methods to achieve this are <strong>Log Shipping</strong> and <strong>Mirroring</strong>. In this article, we will focus on <strong>Log Shipping</strong>.</p><p><strong>What is Log Shipping?</strong></p><p>Log Shipping is a disaster recovery technique that periodically backs up the transaction logs on a <strong>primary server</strong> (Active Mode) and transfers them to a <strong>secondary server</strong> (Standby Mode) as per a predefined schedule.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/795/1*l0PfEOpXJqwBNhLNN7oH_w.png" /></figure><p><strong>How Log Shipping Works</strong></p><p>Log Shipping operates in the following phases:</p><p><strong>1. Regular Backups</strong></p><ul><li>The <strong>primary server</strong> takes transaction log backups at scheduled intervals.</li><li>These backups contain all committed transactions since the last backup.</li></ul><p><strong>2. Transfer of Transaction Log Backups</strong></p><ul><li>The backup files are <strong>automatically copied</strong> from the primary server to the secondary server over the network.</li></ul><p><strong>3. Restoration on the Secondary Server</strong></p><ul><li>The <strong>secondary server restores</strong> these transaction log backups in sequence.</li><li>The database on the secondary server is kept in sync with the primary server.</li><li>The database can be in <strong>Standby Mode</strong> (allowing read-only access) or <strong>No Recovery Mode</strong> (for faster failover readiness).</li></ul><p><strong>4. Failover Process</strong></p><ul><li>If the <strong>primary server goes offline</strong>, the secondary server can take over.</li><li>Failover is a <strong>manual process</strong> in Log Shipping (unlike automatic failover in Mirroring or AlwaysOn Availability Groups).</li><li>In <strong>Standby Mode</strong>, the secondary server can be used for read-only operations before a full failover occurs.</li></ul><h4><strong>Ways to Implement Log Shipping</strong></h4><p>There are two ways of implementing Log Shipping, let’s see in this section.</p><p><strong>1.Manual</strong>:</p><p>Take backups manually and store them in a shared folder or a server using a domain account.</p><p><strong>Step 1: Perform a Full Backup on the Primary Server</strong></p><pre>— -Take a full database backup on the primary server <br>BACKUP DATABASE [YourDatabase] <br>TO DISK = ‘\\SharedFolder\YourDatabase_Full.bak’ <br>WITH FORMAT, INIT, NAME = ‘Full Backup of YourDatabase’;</pre><p><strong>Step 2: Take a Transaction Log Backup on the Primary Server</strong></p><pre>— Take a transaction log backup on the primary server <br>BACKUP LOG [YourDatabase] <br>TO DISK = ‘\\SharedFolder\YourDatabase_TLog.trn’ <br>WITH INIT, NAME = ‘T-Log Backup of YourDatabase’;</pre><p><strong>Step 3: Manually Transfer the Backup Files</strong></p><p>After taking the backups, <strong>manually copy</strong> the .bak and .trn files from the primary server to a shared folder or the secondary server.</p><p><strong>Step 4: Restore the Full Backup on the Secondary Server</strong></p><pre>— Restore the full database backup on the secondary server in NORECOVERY mode <br>RESTORE DATABASE [YourDatabase] <br>FROM DISK = ‘\\SharedFolder\YourDatabase_Full.bak’ <br>WITH NORECOVERY, REPLACE;</pre><p><strong>Step 5: Restore the Transaction Log Backup on the Secondary Server</strong></p><pre>— Restore the transaction log backup on the secondary server in NORECOVERY mode <br>RESTORE LOG [YourDatabase] <br>FROM DISK = ‘\\SharedFolder\YourDatabase_TLog.trn’ <br>WITH NORECOVERY;</pre><p><strong>Automating Log Shipping Using SQL Server Agent Jobs</strong></p><p>Instead of manually running the backups and restores, we can <strong>schedule SQL Server Agent jobs</strong> to automate the process:</p><ol><li><strong>On the Primary Server</strong>:</li><li>Create a SQL Server Agent job that runs <strong>Step </strong>2’s transaction log backup query.</li><li>Schedule it to run <strong>every 15 minutes</strong>.</li></ol><p><strong>On the Secondary Server</strong>:</p><ol><li>Create a SQL Server Agent job that runs <strong>Step </strong>5’s log restore query.</li><li>Schedule it to run <strong>every 15 minutes.</strong></li></ol><p><strong>Failover Process</strong></p><p>In case of primary server failure, restore the secondary database to <strong>full operational mode</strong> using:</p><pre>— Bring the secondary database online after failover <br>RESTORE DATABASE [YourDatabase] WITH RECOVERY;</pre><h4><strong>2.Inbuilt Method (GUI):</strong></h4><p>Use the built-in Log Shipping wizard in SQL Server to automate the backup, copy, and restore process.</p><p><strong>Step 1: Open Log Shipping Wizard</strong></p><ul><li>Right-click on the <strong>primary database</strong> in SQL Server Management Studio (SSMS).</li><li>Navigate to <strong>Tasks</strong> → <strong>Ship Transaction Logs</strong>.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/925/1*PK3max_z55DZsTZ4qYDlYQ.png" /><figcaption>Log Shipping GUI</figcaption></figure><p><strong>Step 2: Enable Log Shipping for the Primary Database</strong></p><ul><li>Check the box <strong>“Enable this as a primary database in log shipping configuration.”</strong></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/835/1*OsqrVjBI89Kehv5aoR6KYw.png" /><figcaption>Log Shipping GUI</figcaption></figure><p><strong>Step 3: Configure the Backup Settings</strong></p><ul><li>Click <strong>Backup Settings</strong> and define the <strong>backup schedule</strong> for transaction log backups.</li><li>Choose a network path or shared folder where backups will be stored.</li><li>Set the retention period for old transaction log backups.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1016/1*sX50WzSWihZFzfxFlGQLvw.png" /><figcaption>Log Shipping GUI</figcaption></figure><p><strong>Step 4: Add a Secondary Server Instance</strong></p><ul><li>Click <strong>Add</strong> to specify the <strong>secondary SQL Server instance</strong>.</li><li>Connect to the instance (ensure it’s under a <strong>domain account</strong> or a second instance on the same machine).</li></ul><p><strong>Step 5: Choose Database Initialization Method</strong></p><p>On the secondary server, choose one of the following options for initializing the database:</p><ul><li><strong>(A) Create a new database:</strong> SQL Server will automatically take a full backup and restore it on the secondary server.</li><li><strong>(B) Use an existing full backup:</strong> If a full backup already exists on the secondary server, specify its location.</li><li><strong>(C)Database is already initialized:</strong> If the database has been restored manually using <strong>NORECOVERY</strong> or <strong>STANDBY</strong> mode, specify the location of the database files.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*izf-oTq5MmZLV6XeTM1BKQ.png" /><figcaption>Log Shipping GUI</figcaption></figure><p><strong>Step 6: Configure Transaction Log Destination</strong></p><ul><li>Set up the destination folder where transaction log backups will be copied and restored on the secondary server.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WzKlrwwLAsGpdZdbqmfdBw.png" /><figcaption>Log Shipping GUI</figcaption></figure><p><strong>Step 7: Choose Database Recovery Mode</strong></p><ul><li><strong>No Recovery Mode:</strong> The secondary database remains non-accessible and is always in restoring mode.</li><li><strong>Standby Mode:</strong> The secondary database allows read-only access for reporting.</li><li>If using <strong>Standby Mode</strong>, switch to <strong>Master Database</strong> and refresh SSMS after configuration.</li><li>This prevents issues with automatic log restoration</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lA4Rna33tqcQD1DqNdPv4w.png" /><figcaption>Log Shipping GUI</figcaption></figure><p><strong>Advantages of Log Shipping</strong></p><ul><li><strong>Simple to configure and maintain</strong>.</li><li><strong>Supports multiple secondary servers</strong>.</li><li><strong>Allows read-only access to the standby database</strong> (useful for reporting).</li><li><strong>Low overhead on the primary server</strong>.</li><li><strong>Useful for disaster recovery and migration scenarios</strong>.</li></ul><p><strong>Limitations of Log Shipping</strong></p><ul><li><strong>No automatic failover</strong> — Requires manual intervention.</li><li><strong>Potential data loss</strong> — Transactions since the last log backup may be lost.</li><li><strong>Latency</strong> — The secondary server is not real-time; it depends on the log shipping frequency.</li><li><strong>Additional storage requirement</strong> — Backup files need to be stored before transfer.</li></ul><p><strong>Conclusion</strong></p><p>Log Shipping is an effective database level disaster recovery solution in SQL Server, providing an easy-to-implement method for maintaining a standby server. While it lacks automatic failover, it offers a cost-effective and simple way to ensure high availability and data redundancy.</p><p>By understanding its prerequisites, working mechanism, and advantages, organizations can leverage Log Shipping to enhance their SQL Server disaster recovery strategy.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=79e411fb46dc" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>