SQL Server on Linux – how does it actually work?
Over the last few weeks I have already written a lot about how to run SQL Server on Linux, Docker, and Kubernetes. But I haven’t yet talked about how SQL Server can actually run on Linux. Therefore, it’s time today to unveil this little secret 🙂 .
When Microsoft first thought about SQL Server on Linux, they have made very fast the decision that a whole source code port of the Windows based SQL Server to Linux doesn’t really work. The code base of SQL Server consists of millions of lines of C++ and Assembler code – porting and testing everything on Linux would have been a huge amount of work, and in the meantime the Windows based SQL Server would have already released a few newer versions.
Therefore, the idea was to run the unmodified Windows based SQL Server directly on Linux. Underneath the hood, we all execute the same assembly instructions on Linux as we do on Windows. Of course, the provided OS libraries and the executable format (ELF vs. PE) are completely different, but it’s still the same CPU instruction set that we use in each OS. In addition, SQL Server already abstracts the thread scheduling and the memory management since SQL Server 2005 in a component called SQLOS. Therefore, some dependencies to the underlying OS are already loosely-coupled in the perspective of SQL Server.
But SQLOS itself was too less to be able to run the same, identical Windows based SQL Server on Linux. Therefore, the SQL Server development team has reused a research prototype OS called Drawbridge to be able to run SQL Server on Linux. The idea of Drawbridge is to abstract an entire OS within a user process component on a host OS. It’s just like a container that runs an OS – they call it an Library OS.
One of the primary tasks of a Library OS is it to map kernel calls from one OS to another OS. Therefore, a client application (like SQL Server) can still call an original Windows 32 API function, and underneath (within the Library OS) that API function is translated to the call of the correct API function within the Linux Kernel.
Exploring SQL Server on Linux
This sounds now all very theoretically. Therefore, it’s now time to explore how SQL Server on Linux actually works. When you have followed one of my last blog postings, you should have a working installation of SQL Server running on Linux. As soon as you have installed SQL Server on Linux, you have also installed a stripped-down version of Windows – that’s the Library OS. And that stripped-down version of Windows is packaged in so-called sfp files on Linux. You can see all these sfp files in the folder /opt/mssql/lib:
Besides these sfp files, there are also some shared object files (with the extension .so), which are compiled library files. You can compare them to DLL files on a Windows system.
During my research I have also found a tool called sfpack with which you can explore the content of these sfp files. I have compiled the source code of sfpack on my Linux system, and now let’s examine the sqlservr.sfp file with it, which contains the binaries of our Windows based SQL Server.
As you can see from the output, these are the exact same files as you would see on a Windows based installation of SQL Server. These are the same binaries. Let’s have now a look into the system.sfp file, which contains parts of the stripped-down version of the Windows OS:
Again, you can see the same .dll and .sys files as you would see on a Windows installation. But in addition you also have files with an extension .dbpatch. It seems (unverified from my side!) that Microsoft just “patches” the Windows system calls on the fly to their corresponding calls into the Linux Kernel. This is really amazing stuff!
All these sfp files are container files that consists of Windows executables (OS and SQL Server). But how is now SQL Server started up on Linux? SQL Server runs as a system service on Linux. System services on Linux are controlled through systemd. systemd is a System and Service Manager, and you can use the utility program systemctl to control the various services. Let’s have a look on the status of our SQL Server service:
systemctl status mssql-server
As you can see, SQL Server is currently up and running and uses the PID (process ID) 1458. If you wonder why you have two PIDs for SQL Server, you have to check out this blog posting. The configuration of the SQL Server service is stored in the file /lib/systemd/system/mssql-server.service. Let’s have a look on this file:
As you can see, the [Service] section of this file references the executable /opt/mssql/bin/sqlservr, which is executed under the user mssql. This executable is a traditional Linux based ELF binary file, which you can verify with the following command:
objdump /opt/mssql/bin/sqlservr -f
The main goal of this Linux executable is to startup the Library OS (from the various provided sfp files), and finally to execute the Windows based SQL Server. And everything else the same as on Windows :-).
Running an unmodified version of SQL Server on Linux is a real piece of engineering. But as you have seen throughout this blog posting, it’s not that hard if you understand how the underlying architecture works, and how Microsoft is actually doing it. Unfortunately, the underlying technology – Drawbridge – is a closed source project from Microsoft. Otherwise it would be quite funny to run other applications directly, without any modifications on Linux. But who knows what the future brings.
If you want to learn more about SQL Server on Linux, Docker, and Kubernetes, I highly suggest my upcoming Live Online Training on May 13 and May 14, where I will do a more technical deep-dive about all these exiting new technologies that will change our life as SQL Server Developers and DBAs over the next years.
Thanks for your time,