diff --git a/DC-SBP-SLES-SQL b/DC-SBP-SLES-SQL new file mode 100644 index 00000000..907ef443 --- /dev/null +++ b/DC-SBP-SLES-SQL @@ -0,0 +1,19 @@ +MAIN="SLES-SQL-server-linux.adoc" + +ADOC_TYPE="article" + +ADOC_POST="yes" + +ADOC_ATTRIBUTES="--attribute docdate=2024-11-16" + +# stylesheets +STYLEROOT=/usr/share/xml/docbook/stylesheet/sbp +FALLBACK_STYLEROOT=/usr/share/xml/docbook/stylesheet/suse2022-ns + +XSLTPARAM="--stringparam publishing.series=sbp" + +DRAFT=yes +ROLE="sbp" +#PROFROLE="sbp" + +DOCBOOK5_RNG_URI="http://docbook.org/xml/5.2/rng/docbookxi.rnc" diff --git a/adoc/SLES-SQL-server-linux-docinfo.xml b/adoc/SLES-SQL-server-linux-docinfo.xml new file mode 100644 index 00000000..71896472 --- /dev/null +++ b/adoc/SLES-SQL-server-linux-docinfo.xml @@ -0,0 +1,92 @@ + + + + + https://github.com/SUSE/suse-best-practices/issues/new + Microsoft SQL Server on SUSE Linux Enterprise Server + + + + + + +SLES 15 SP6+, SQL Server 2022 + + +Best Practices Documentation +Getting Started + +SUSE Linux Enterprise Server 15 SP6+ +Microsoft SQL Server 2022 + + + + + Bernd + Schubert + + + + SUSE + + + + + Gereon + Vey + + + + SUSE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This guide helps users install and configure a basic Microsoft SQL Server + deployment on SUSE Linux Enterprise Server. + + Disclaimer: + Documents published as part of the SUSE Best Practices and the Technical Reference Documentation series have been contributed voluntarily + by SUSE employees and third parties. They are meant to serve as examples of how particular + actions can be performed. They have been compiled with utmost attention to detail. + However, this does not guarantee complete accuracy. SUSE cannot verify that actions described + in these documents do what is claimed or whether actions described have unintended consequences. + SUSE LLC, its affiliates, the authors, and the translators may not be held liable for possible errors + or the consequences thereof. + diff --git a/adoc/SLES-SQL-server-linux.adoc b/adoc/SLES-SQL-server-linux.adoc new file mode 100644 index 00000000..a45a67d0 --- /dev/null +++ b/adoc/SLES-SQL-server-linux.adoc @@ -0,0 +1,1265 @@ +:docinfo: + +// = {title} += Microsoft SQL Server on SUSE Linux Enterprise Server +// SUSE Linux Enterprise Server 15 SP6+, SQL Server 2022 +// :author: Bernd Schubert, Gereon Vey +:revnumber: 0.0.2 +:toc2: +:toc-title: Microsoft SQL Server on SUSE Linux Enterprise Server +:toclevels: 4 + +:sles: SUSE Linux Enterprise Server +:sqls: SQL Server + +image:sqlserver.svg[SQL Server,400,400] + +== Motivation + +=== Background + +Since Microsoft released {sqls} for Linux in 2017 (footnote:[https://cloudblogs.microsoft.com/sqlserver/2017/10/02/sql-server-2017-on-windows-linux-and-docker-is-now-generally-available]), +the feature gap (footnote:[https://learn.microsoft.com/en-us/sql/sql-server/what-s-new-in-sql-server-2022?view=sql-server-ver16&viewFallbackFrom=sql-server-linux-ver16]) for SQL Server between +Windows and Linux has been closing quickly with each update. Aside from some niche features +(footnote:[https://learn.microsoft.com/en-us/sql/sql-server/what-s-new-in-sql-server-2022?view=sql-server-ver16&viewFallbackFrom=sql-server-linux-ver16]), +it's now extremely viable to consider running {sqls} workloads on Linux, with the 2022 release (footnote:[https://learn.microsoft.com/en-us/sql/sql-server/sql-server-2022-release-notes?view=sql-server-ver16&preserve-view=true]). + +=== Business case of why SQL on SUSE + +SUSE has a long history of been used as a host for commercial databases within the linux world. Many of the initial developments and ports of well know commercial databases to linux where done on and with SUSE. +SUSE Linux Enterprise Server was first with many linux features used by modern databases like memory handling, filesystems and provides a rock solid base for business workloads. + +Microsoft is making SQL Server a platform that gives you choices of development languages, data types, on-premises or cloud, and operating systems by bringing the power of SQL Server to Linux, Linux-based Docker containers, and Windows. +Many organizations, especially those that have used SQL Server on Windows are moving to Linux too, and now have the benefit to have their database available there. +SQL on SUSE is Enterprise-ready with great performance. The TPC-H benchmark results done by HP show that SQL Server on Linux delivers amazing performance. SUSE Linux proved to be faster than Windows in that benchmark too. +This really showcases that SQL Server’s functionality, its' performance, and scaleability are also there when deployed to SUSE Linux Enterprise Server. +Second, there is no difference when running SQL Server on Linux as for example the you use as developer on windows are the same as with linux. +As Linux administrator you feel at home too, as SQL Server is installed and updated like any other linux package using zypper or YaST2. + +=== Audience + +This guide is intended for {sqls} DBAs, Developers, and DevOps/SRE engineers who are familiar with SQL Server on Windows and are looking +to migrate to Linux. Operators who are adding a {sqls} requirement into a primarily Linux environment may prefer tools that run only on Linux servers for consistency and simplicity. +Another reason may be lower negotiated pricing for Linux subscriptions to replace existing {sqls} on Windows machines. + +=== Scope + +The guide covers a basic installation of {sqls} on {sles} including the OS tuning specific for {sqls} +It is meant to be agnostic of underlying infrastructure excepting the nuance of registering your server discussed in <> <>. + + +== Installation + +At first the manual installation for a standalone {sqls} is described by starting at <>. +The automated installation based on Ansible is decribed in<>. + +[id="man_inst"] +=== System requirements +.SQL Server has the following system requirements for Linux: +* 2 GHz CPU with 2 cores +* x64-compatible only +* 2 GB¹ RAM +* XFS or Ext4 file system for the SQL DB files +** other file systems, such as BTRFS, aren't support +* 6 GB disk space (not including data) +* swap space >= 2 GB + +//- + +.If you use Network File System (NFS) remote shares in production, note the following support requirements: +* Use NFS version 4.2 or higher. Older versions of NFS don't support required features, such as fallocate and sparse file creation, common to modern file systems. +* Locate only the /var/opt/mssql directories on the NFS mount. Other files, such as the SQL Server system binaries, aren't supported. + +¹ 2 GB is the minimum required memory to start SQL Server on Linux, which accommodates system threads and internal processes. You must take this amount into consideration when setting *max server memory* and *MemoryLimitMB*. + +[id="server_registration"] +=== Server registration + +To gain access to SUSE repositories, you first need to register your server with `SUSEConnect`. If you are launching an On-Demand (or Pay-As-You-Go) +instance and not a BYOS (Bring Your Own Subscription) instance at a public cloud provider, skip this step. + +[source,shell] +---- +sudo SUSEConnect --regcode ${REGISTRATION_CODE} --email ${EMAIL_ADDRESS} +---- + + +Alternatively, if you have access to a + +* SUSE https://documentation.suse.com/sles/15-SP6/single-html/SLES-rmt/#book-rmt[RMT] (Repository Mirroring Tool) +* or https://documentation.suse.com/suma/5.0/[SUSE Manager] +* or https://scc.suse.com/[SCC] (SUSE Customer Center) + +server you want to use, use the `--url` option instead. + +[source,shell] +---- +sudo SUSEConnect --url ${REGISTRATION_SERVER_URL} +---- + +More information about registering can be found in the https://documentation.suse.com/sles/15-SP6/single-html/SLES-deployment/#sec-yast-install-scc-registration[{sles} 15 SP6 Deployment Guide]. + + +=== Repositories +Configure repositories for installation and upgrade of {sqls} 2022 on Linux. +To verify packages from Microsoft’s {sqls} repositories, first add their package signing key: +As non privileged user the `sudo` must be added in front of each command. + +[source,shell] +---- +sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc +---- + +Then add the repository. + +[source,shell] +---- +sudo zypper ar https://packages.microsoft.com/config/sles/15/mssql-server-2022.repo +sudo zypper ar https://packages.microsoft.com/config/sles/15/prod.repo +sudo zypper --gpg-auto-import-keys refresh +---- + +The `mysql-server` package requires `gdb` from the development tools module (which in turn needs desktop applications module): + +[source,shell] +---- +sudo SUSEConnect -p sle-module-desktop-applications/15.6/x86_64 +sudo SUSEConnect -p sle-module-development-tools/15.6/x86_64 +---- + +Optional: the sle-ha module is needed for a High Availability (HA) setup: + +[source,shell] +---- +sudo SUSEConnect -p sle-ha/15.6/x86_64 +---- + +=== Package Installation + +To install the {sqls} package non-interactively and add-ons, run the following command: + +[source,shell] +---- +sudo ACCEPT_EULA=Y zypper install -y mssql-server mssql-tools18 unixODBC-devel glibc-locale-base sqlcmd tuned +---- + +[id="ansi_inst"] +=== Automated Deployment with Ansible + + +== Configuration + +=== Initial configuration + +This section is covering the OS modification, the NIC configuration, the recommended storage setup and the {sqls} configuration. + +==== OS configuration (CPU, Kernel, Memory) + +[discrete] +==== CPU/sysctl/disk/memory setting +{sles} contains a `TuneD` profile for mssql (within the `tuned` package), but it's not according to the {sqls} best practices guide. The next steps describe and line out the changes recommended for {sqls}. +Using TuneD it automatically configures CPU frequency governor, ENERGY_PERF_BIAS, and min_perf_pct settings appropriately due to the `throughput-performance` profile being used as base for the `mssql profile`. +C-States parameter must be configured manually. The disk readahead section is also covered by including the file `throughput-performance`, please check the settings if they are equal and skip them if not needed. + +.Create a mssql profile +[source,shell] +---- +mkdir -p /etc/tuned/mssql +cat >/etc/tuned/mssql/tuned.conf <>) + +[source,shell] +---- +update-bootloader --refresh +reboot +---- + +After the reboot verify the setting is persistent. +[source,shell] +---- +cat /proc/cmdline +---- + +[discrete] +==== Tunning storage IO + +INFO: As multipath I/O is often used for {sqls} deployments, configure the device mapper (DM) multi-queue target to use the blk-mq infrastructure, by enabling the dm_mod.use_blk_mq=y kernel boot option. The default value is n (disabled). This setting, when the underlying SCSI devices are using blk-mq, reduces locking overhead at the DM layer. For more information on how to configure multipath I/O, can be found at https://documentation.suse.com/sles/15-SP6/single-html/SLES-storage/#cha-multipath or https://www.suse.com/support/kb/doc/?id=000021020 + +SCHEDULER is one of bfq, none, kyber, or mq-deadline. DEVICE is the block device (sda for example). For permanent I/O scheduler change (reboot persistent) for a particular device, copy `/usr/lib/udev/rules.d/60-io-scheduler.rules` to `/etc/udev/rules.d/60-io-scheduler.rules`, and edit the copied file to suit the needs. + +.Copy `60-io-scheduler.rules` +[source,shell] +---- +cp /usr/lib/udev/rules.d/60-io-scheduler.rules /etc/udev/rules.d/60-io-scheduler.rules +---- + +.Unchanged file +[source,shell] +---- +... +# 1. BFQ scheduler for single-queue HDD +ATTR{queue/rotational}!="0", TEST!="%S%p/mq/1", ATTR{queue/scheduler}="bfq", GOTO="scheduler_end" + +# 2. BFQ scheduler for every HDD, including "real" multiqueue +# ATTR{queue/rotational}!="0", ATTR{queue/scheduler}="bfq", GOTO="scheduler_end" + +# 3. For "real" multiqueue devices, the kernel defaults to no IO scheduling +# Uncomment this (and select your scheduler) if you need an IO scheduler for them +# TEST=="%S%p/mq/1", ATTR{queue/scheduler}="kyber", GOTO="scheduler_end" + +# 4. BFQ scheduler for every device (uncomment if you need ionice or blk-cgroup features) +# ATTR{queue/scheduler}="bfq", GOTO="scheduler_end" + +# 5. mq-deadline is the kernel default for devices with just one hardware queue +# ATTR{queue/scheduler}="mq-deadline" +---- + +The example above shows option 1 uncommented. Depending on the disk type choose between option 1 to 5 or add a personal one. +The old default must be deactivated by comment the line with a `#`. + +.new setting +[source,shell] +---- +... +# 1. BFQ scheduler for single-queue HDD +# ATTR{queue/rotational}!="0", TEST!="%S%p/mq/1", ATTR{queue/scheduler}="bfq", GOTO="scheduler_end" + +# 2. BFQ scheduler for every HDD, including "real" multiqueue +# ATTR{queue/rotational}!="0", ATTR{queue/scheduler}="bfq", GOTO="scheduler_end" + +# 3. For "real" multiqueue devices, the kernel defaults to no IO scheduling +# Uncomment this (and select your scheduler) if you need an IO scheduler for them +# TEST=="%S%p/mq/1", ATTR{queue/scheduler}="kyber", GOTO="scheduler_end" + +# 4. BFQ scheduler for every device (uncomment if you need ionice or blk-cgroup features) +# ATTR{queue/scheduler}="bfq", GOTO="scheduler_end" + +# 5. mq-deadline is the kernel default for devices with just one hardware queue +# ATTR{queue/scheduler}="mq-deadline" +### new entry +ATTR{queue/scheduler}="kyber" +---- + +Activate the setting during runtime and check the configuration for all devices starting with `sd`. +.udevadm usage +[source,shell] +---- +udevadm control --reload +udevadm trigger +cat /sys/block/sd?/queue/scheduler +---- + +==== Network configuration + +The network setting depend on the used NIC hardware. Some of the following configuration changes maybe can't be made or have different possible values as shown. +In the following step the execution as root user is described. If the root access is not possible the `sudo` command must be added in front of each command. + +[discrete] +==== Configuring network port buffer size +In the example below, the NIC is named eth1, which is an Intel-based NIC. +For Intel based NIC, the recommended buffer size is 4 KB (4096). The value to use here depends on the maximum values recommended for each NIC type and vendor. +Make the `ethtool` option persistent by adding them to the ifcfg file for each interface (last line). + +.read the current setting +[source,shell] +---- +ethtool -g eth1 +Ring parameters for eth1: +Pre-set maximums: +RX: 4096 +RX Mini: n/a +RX Jumbo: n/a +TX: 4096 +TX push buff len: n/a +Current hardware settings: +RX: 256 +RX Mini: n/a +RX Jumbo: n/a +TX: 256 +RX Buf Len: n/a +CQE Size: n/a +TX Push: off +RX Push: off +TX push buff len: n/a +TCP data split: n/a +---- + +.set the new values +[source,shell] +---- +vi /etc/sysconfig/network/ifcfg-eth1 +IPADDR='192.168.1.11/24' +BOOTPROTO='static' +STARTMODE='auto' +ZONE=internal +ETHTOOL_OPTIONS='-G iface rx 4096 tx 4096' +---- + +Restart the NIC and validate the setting or do all the changes in once and restart the network later. +[id="nic-restart"] +.NIC restart +[source,shell] +---- +ifdown eth1 + +ifup eth1 + +ethtool -?? eth1 +---- + +.For the concrete example it looks like this +[source,shell] +---- +ethtool -g eth1 +... +Current hardware settings: +RX: 4096 +RX Mini: n/a +RX Jumbo: n/a +TX: 4096 +... +---- + +Enable the network port buffer temporarily using the command below and check the settings. +[source,shell] +---- +ethtool -G eth1 rx 4096 tx 4096 +ethtool -g eth1 +---- + +[discrete] +==== Enable jumbo frames +Before enabling jumbo frames, verify that all the network switches, routers, and anything else essential in the network packet path between the clients and the {sqls} support jumbo frames. +Add a line in the ifcfg file and set the MTU size. + +[source,shell] +---- +vi /etc/sysconfig/network/ifcfg-eth1 +... +MTU=9000 +... +---- + +Restart your NIC e.g. <> and validate the setting. +[source,shell] +---- +ip addr |grep 'mtu 9' +---- + +Enable jumbo frames temporarily using the command `ip`. +[source,shell] +---- +ip link set eth1 mtu 9000 +ip addr |grep 'mtu 9' +---- + +If your {sqls} is running to this point in time, than the {sqls} needs to be configured for jumbo frames as well. +After jumbo frames are enabled, connect to SQL Server and change the network packet size to 8060 using `sp_configure` as shown. +(How to connet to the database? <>) + +[id="sql-jumbo"] +.Jumbo frames for {sqls} +[source,sql] +---- +EXEC sp_configure 'network packet size', '8060'; +GO +RECONFIGURE WITH OVERRIDE; +GO +---- + +[discrete] +==== Setting the port for adaptive RX/TX IRQ coalescing +Meaning interrupt delivery is adjusted to improve latency when the packet rate is low and improve throughput when the packet rate is high. +This setting might not be available across all the different network infrastructures, so review the existing network infrastructure and confirm that this is supported. +The example below is for the NIC named eth1, which is an Intel-based NIC. + +[source,shell] +---- +vi /etc/sysconfig/network/ifcfg-eth1 +... +ETHTOOL_OPTIONS_rx='-C iface adaptive-rx on adaptive-tx on' +---- + +Restart the NIC <> and validate the settings. +[source,shell] +---- +ethtool -c eth1 +---- + +Enable the RX/TX IRQ coalescing temporarily using the command `ethtool`. +[source,shell] +---- +ethtool -C eth1 adaptive-rx on adaptive-tx on +ethtool -c eth1 +---- + +[discrete] +==== RX and TX side of RSS queues +It is recommended receive-side scaling (RSS) is enabled and by default, combining the RX and TX side of RSS queues +There have been specific scenarios, when working with Microsoft Support, where disabling RSS has improved the performance as well. +Test this setting in test environments before applying it on production environments. The following example is for Intel NICs. +[source,shell] +---- +vi /etc/sysconfig/network/ifcfg-eth1 +... +ETHTOOL_OPTIONS_com='-L iface combined 8' +---- + +Restart the NIC <> and validate the settings. +[source,shell] +---- +ethtool -l eth1 +---- + +Enable combining the RX and TX side of RSS queues temporarily using the command `ethtool` and verify the setting. +[source,shell] +---- +ethtool -L eth1 combined 8 +ethtool -l eth1 +---- + +==== Firewall configuration + +The connection to the {sqls} needs two ports opened in the firewall. +* 135/tcp MSDTC +* 1433/tcp {sqls} + +//- + +optional: +* 9100/tcp Prometheus node_exporter +* 9664/tcp ha_cluster_exporter + +[source,shell] +---- +firewall-cmd --permanent --add-port=135/tcp --add-port=1433/tcp && firewall-cmd --reload +---- + +.Check the configuration +[source,shell] +---- +firewall-cmd --list-ports +---- + +==== Storage configuration + +Use storage subsystem with appropriate IOPS, throughput, and redundancy. Based on the Microsoft {sqls} recommendation splitting the storage into 5 parts is the best approach. + +* OS + swap (mount point / and /swap) +* data (mount point /data) +* transaction log (mount point /log) +* tempdb (mount point /tempdb) + +The default filesystem for OS will be btrfs all others will have xfs. Based on the database sizing the required disk must be provided. The example will decribe a Linux Software RAID based setup. +The disk `sdb - sdh` are the partitions from the NVME storage underneath. The command `lsblk` helps to find the right partition name to build a reasonable RAID setup later and avoid having all partitions +from only one NVME in the same RAID configuration. + +INFO: The following chapter is done as `root` user, if this is not possible the `sudo` must be put in front of each command. + +.Creating the database storage RAID +[source,shell] +---- +# For Data volume, using 4 devices, in RAID 5 configuration with 8KB stripes +mdadm --create --verbose /dev/md0 --level=raid5 --chunk=8K --raid-devices=4 /dev/sdb /dev/sdc /dev/sdd /dev/sde + +# For Log volume, using 2 devices in RAID 10 configuration with 64KB stripes +mdadm --create --verbose /dev/md1 --level=raid10 --chunk=64K --raid-devices=2 /dev/sdg /dev/sdf + +# For tempdb volume, using 2 devices in RAID 0 configuration with 64KB stripes +mdadm --create --verbose /dev/md2 --level=raid0 --chunk=64K --raid-devices=2 /dev/sdi /dev/sdh +---- + +The ext4 and XFS filesystem is supported, therefore formatting the volumes with XFS (case sensitive). +[source,shell] +---- +mkfs.xfs /dev/md0 -f -n version=ci -L datavolume +mkfs.xfs /dev/md1 -f -n version=ci -L logvolume +mkfs.xfs /dev/md2 -f -n version=ci -L tempdb +---- + +Use the `noatime` attribute with any filesystem that stores {sqls} data and log files. Creating the mount point: + +[source,shell] +---- +mkdir -p /data /log /tempdb +---- + +Mounting the disks during boot requires an entry in the `/etc/fstab`. The `blkid` helps to find the right `UUID` for each disk. + +[source,shell] +---- +blkid |grep md + +vi /etc/fstab +... +UUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" /data xfs rw,attr2,noatime 0 0 +UUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" /log xfs rw,attr2,noatime 0 0 +UUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" /tempdb xfs rw,attr2,noatime 0 0 + +mount -a +---- + +.creating subdirectories for the {sqls} +[source,shell] +---- +mkdir -p /data/masterdata /log/masterlog +---- + +Prepare filesystem permission for the dedicated storage partition: + +[source,shell] +---- +chown -R mssql.mssql /data /tempdb /log +---- + +Check the disk are mounted and have the right permissions: + +[source,shell] +---- +df -hT +ls -l / +---- + +INFO: This would be a good point in time to reboot your system to activate all the configuration changes and settings before the {sqls} is started the first time. This would also help to check if all settings made before are reboot persistent. + +[id="final_reboot"] +.server reboot +[source,shell] +---- +reboot +---- + +==== {sqls} configuration +To configure and start {sqls}, `mssql-conf` can be used to accept the EULA, set the {sqls} Edition, the SA password and many more details. + +Add `mssql-tools18` to your `PATH` environment variable in a bash shell: +[source,shell] +---- +echo 'export PATH="$PATH:/opt/mssql-tools18/bin"' >> ~/.bash_profile +echo 'source ~/.bash_profile"' >> ~/.bashrc +source ~/.bash_profile +---- + +Running the command `/opt/mssql/bin/mssql-conf list` will a list of all possible parameter what can be set. + +[source,shell] +---- +/opt/mssql/bin/mssql-conf list +control.alternatewritethrough Enable optimized write through flush for O_DSYNC requests +control.hestacksize Host extension stack size in KB +control.stoponguestprocessfault Stops the process if any guest process reports unhandled exception +control.writethrough Use O_DSYNC for file flag write through requests +coredump.captureminiandfull Capture both mini and full core dumps +coredump.coredumptype Core dump type to capture: mini, miniplus, filtered, full +coredump.disablecoredump SQL Server disable core dump +distributedtransaction.allowonlysecurerpccalls Configure secure only rpc calls for distributed transactions +distributedtransaction.fallbacktounsecurerpcifnecessary Configure security only rpc calls for distributed transactions +distributedtransaction.maxlogsize DTC log file size in MB. Default is 64MB +distributedtransaction.memorybuffersize Circular buffer size in which traces are stored. This size is in MB and default is 10MB +distributedtransaction.servertcpport MSDTC rpc server port +distributedtransaction.trace_cm Traces in the connection manager +distributedtransaction.trace_contact Traces the contact pool and contacts +distributedtransaction.trace_gateway Traces Gateway source +... +---- + +The following options are use to do a simple setup for a host with 1TB RAM. +[source,shell] +---- +/opt/mssql/bin/mssql-conf set sqlagent.enabled true +/opt/mssql/bin/mssql-conf set sqlagent.errorlogfile /log/sqlagent.log +/opt/mssql/bin/mssql-conf set sqlagent.errorlogginglevel 2 +/opt/mssql/bin/mssql-conf set telemetry.customerfeedback false +/opt/mssql/bin/mssql-conf set filelocation.defaultdatadir /data +/opt/mssql/bin/mssql-conf set filelocation.defaultlogdir /log +/opt/mssql/bin/mssql-conf set filelocation.masterdatafile /data/masterdata/master.mdf +/opt/mssql/bin/mssql-conf set filelocation.masterlogfile /log/masterlog/mastlog.ldf +/opt/mssql/bin/mssql-conf set network.rpcport 135 +/opt/mssql/bin/mssql-conf set control.writethrough 1 +/opt/mssql/bin/mssql-conf set control.alternatewritethrough 0 +# e.g. using 950GB of 1048576MB available RAM for MSSQL DB instead of 80% default, example for 1TB +/opt/mssql/bin/mssql-conf set memory.memorylimitmb 950000 +---- + +[discrete] +==== Initial setup and start of {sqls} +Finally configure and start `msql-server` (`mssql-conf` starts the `msql-server` immediately after configuring), +run the following command: + +[source,shell] +---- +ACCEPT_EULA='Y' MSSQL_PID='Developer' MSSQL_SA_PASSWORD='Strong!Passw0rd' /opt/mssql/bin/mssql-conf setup +#alternatively +MSSQL_MEMORY_LIMIT_MB='' ACCEPT_EULA='Y' MSSQL_PID='Developer' MSSQL_SA_PASSWORD='Strong!Passw0rd' /opt/mssql/bin/mssql-conf setup +---- + +* `ACCEPT_EULA` accepts the SQL Server EULA +* `MSQL_SA_PASSWORD` sets the SA user password. Ensure password requirements as outlined in <> are followed. +* `MSQL_PID` sets the SQL Server edition, acceptable values are: +** Evaluation +** Developer +** Express +** Web +** Standard +** Enterprise +** EnterpriseCore +** A product key + +WARNING: It is recommended to change the SA password later with `mssql-conf set-sa-password` +or disable the history prior to configuring SQL Server with `set +o history`, and re-enabling it afterward with `set -o history` (Bash). + +If specifying a `product key`, it must be in the form of #####-#####-#####-#####-#####, where '#' is a number or a letter. + +- {sqls} should be started at this point. You can verify this with `systemctl status mssql-server.service`. +- {sqls} listens for connections on port `1433` by default, that's a second option to verify the {sqls} is up and running. +- {sqls} should be accessible with `sqlcmd`. + +.systemd check +[source,shell] +---- +systemctl status mssql-server.service + +● mssql-server.service - Microsoft SQL Server Database Engine + Loaded: loaded (/usr/lib/systemd/system/mssql-server.service; enabled; preset: disabled) + Active: active (running) since Thu 2024-10-17 17:21:22 CEST; 7min ago + Docs: https://docs.microsoft.com/en-us/sql/linux + Main PID: 12965 (sqlservr) + Tasks: 180 + CPU: 16.947s + CGroup: /system.slice/mssql-server.service + ├─12965 /opt/mssql/bin/sqlservr + └─12970 /opt/mssql/bin/sqlservr +---- + +.open port +[source,shell] +---- +ss -tulpan |grep 1433 +tcp LISTEN 0 128 0.0.0.0:1433 0.0.0.0:* users:(("sqlservr",pid=23066,fd=102)) +tcp ESTAB 0 0 127.0.0.1:53189 127.0.0.1:1433 users:(("sqlservr",pid=23066,fd=137)) +tcp ESTAB 0 0 127.0.0.1:35775 127.0.0.1:1433 users:(("sqlservr",pid=23066,fd=122)) +tcp ESTAB 0 0 127.0.0.1:1433 127.0.0.1:53189 users:(("sqlservr",pid=23066,fd=135)) +tcp ESTAB 0 0 127.0.0.1:1433 127.0.0.1:35775 users:(("sqlservr",pid=23066,fd=134)) +tcp ESTAB 0 0 127.0.0.1:33679 127.0.0.1:1433 users:(("sqlservr",pid=23066,fd=108)) +tcp ESTAB 0 0 127.0.0.1:1433 127.0.0.1:33679 users:(("sqlservr",pid=23066,fd=139)) +tcp LISTEN 0 128 *:1433 *:* users:(("sqlservr",pid=23066,fd=105)) +---- + +[id="login_db"] +.sqlcmd login with `sqlcmd -S -U SA -P ` +[source,shell] +---- +sqlcmd -S mssql -U SA -P Strong\!Passw0rd -Q "SELECT @@VERSION" 2>/dev/null + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +Microsoft SQL Server 2022 (RTM-CU15-GDR) (KB5046059) - 16.0.4150.1 (X64) + Sep 25 2024 17:34:41 + Copyright (C) 2022 Microsoft Corporation + Developer Edition (64-bit) on Linux (SUSE Linux Enterprise Server 15 SP6) + +(1 row affected) +---- + +[discrete] +==== Tempdb files movement to a dedicate storage area +By default, a new installation of SQL Server on Linux creates multiple tempdb data files, based on the number of logical cores (with up to eight data files). +One of our preparation steps for the storage part was having a dedicated RAID set for the tempdb files. This setting can only be modified from inside the {sqls}. +The following example moves `tempdb` from its current default location on the disk to another disk location. Because tempdb is re-created each time the +MSSQLSERVER service is started, you do not have to physically move the data and log files. The files are created when the service is restarted. +Until the service is restarted, tempdb continues to function in its existing location. Determine the logical file names of the tempdb database and their current location on disk. + +.check the current location and decided if a move is required or not with `sqlcmd -S -U SA -P ` +[source,sql] +---- +sqlcmd -S mssql -U SA -P Strong\!Passw0rd +SELECT name, physical_name +FROM sys.master_files +WHERE database_id = DB_ID('tempdb'); +GO +---- + +INFO: If this is the first time the database is up and running enable the jumbo frames for the {sqls} if needed. +<> + +If all the preparation are made in the right order the `/tempdb` directory should already be in use and set as default location. In that situation the next step can be skipped. + +.Change the location of each file by using `ALTER DATABASE` with `sqlcmd -S -U SA -P ` +[source,sql] +---- +sqlcmd -S mssql -U SA -P Strong\!Passw0rd +USE master; +GO +ALTER DATABASE tempdb +MODIFY FILE (NAME = tempdev, FILENAME = '/tempdb/tempdb.mdf'); +GO +ALTER DATABASE tempdb +MODIFY FILE (NAME = templog, FILENAME = '/tempdb/templog.ldf'); +GO +ALTER DATABASE tempdb +MODIFY FILE (NAME = tempdev2, FILENAME = '/tempdb/tempdb2.ndf'); +GO +ALTER DATABASE tempdb +MODIFY FILE (NAME = tempdev3, FILENAME = '/tempdb/tempdb3.ndf'); +GO +ALTER DATABASE tempdb +MODIFY FILE (NAME = tempdev4, FILENAME = '/tempdb/tempdb4.ndf'); +GO +---- + +Stop and restart the instance of {sqls}. + +.Verify the file change with `sqlcmd -S -U SA -P ` +[source,sql] +---- +sqlcmd -S mssql -U SA -P Strong\!Passw0rd +SELECT name, physical_name +FROM sys.master_files +WHERE database_id = DB_ID('tempdb'); +GO +---- + +[source,shell] +---- +ls -lh /tempdb/* +-rw-rw---- 1 mssql mssql 8,0M 11. Nov 11:05 /tempdb/tempdb2.ndf +-rw-rw---- 1 mssql mssql 8,0M 11. Nov 11:05 /tempdb/tempdb3.ndf +-rw-rw---- 1 mssql mssql 8,0M 11. Nov 11:05 /tempdb/tempdb4.ndf +-rw-rw---- 1 mssql mssql 8,0M 11. Nov 11:05 /tempdb/tempdb.mdf +-rw-rw---- 1 mssql mssql 8,0M 11. Nov 11:09 /tempdb/templog.ldf +---- + +Delete the tempdb.mdf and templog.ldf files from their original location. + +With {sqls} 16 more memory specific improvements are made with can be enabled. For more detais and {sqls} specific internal tunnings follow the official documentation from Microsoft. +https://learn.microsoft.com/en-us/sql/relational-databases/in-memory-database?view=sql-server-linux-ver16#memory-optimized-tempdb-metadata + +[discrete] +==== Further {sqls} configuration modification +For further configuration, use `mssql-conf` to set additional parameters. Changes will take effect after a restart: + +[source,shell] +---- +mssql-conf set ${parameter} +systemctl restart mssql-server +---- + +Available `mssql-conf` options are described in https://learn.microsoft.com/en-us/sql/linux/sql-server-linux-configure-mssql-conf?view=sql-server-ver16[Configure SQL Server on Linux with the mssql-conf tool]. + +An alternative way to configure {sqls} is using the `/var/opt/mssql/mssql.conf` file. +Settings are stored in the `mssql.conf` format https://learn.microsoft.com/en-us/sql/linux/sql-server-linux-configure-mssql-conf?view=sql-server-ver16#mssqlconf-format[mssql.conf]. + +A sample `mssql.conf` file is shown below. Edit the `mssql.conf` file and restart `mssql-server` to apply changes. + +[source,ini] +---- +[sqlagent] +enabled = true +errorlogginglevel = 2 +errorlogfile = /log/sqlagent.log + +[telemetry] +customerfeedback = false + +[filelocation] +defaultdatadir = /data +defaultlogdir = /log +masterdatafile = /data/masterdata/master.mdf +masterlogfile = /log/masterlog/mastlog.ldf + +[network] +rpcport = 135 + +[EULA] +accepteula = Y + +[control] +writethrough = 1 +alternatewritethrough = 0 +---- + +//// +== High Avaibility Setup +//// + +== Tools + +Now that SQL Server is running, you can query it. The `mssql-tools` package includes `sqlcmd`, which is a shell to query SQL Server. +Install it similarly to the `mssql-server` package. (skip the step if it was done in the chapter Repositories) + +.Add the repository +[source,shell] +---- +zypper addrepo --refresh --check https://packages.microsoft.com/config/sles/15/prod.repo +---- + +.Install the `mssql-tools` package +[source,shell] +---- +ACCEPT_EULA=Y zypper install --no-confirm mssql-tools +---- + +.Add the tools to your `PATH` +[source,shell] +---- +vi ~/.bashrc +echo 'export PATH="$PATH:/opt/mssql-tools18/bin"' >> ~/.bash_profile +source ~/.bash_profile +---- + +Then start `sqlcmd` and input a query. The `-S` option designates the server. The `-U` option specifies the user. +Available options can be found at https://docs.microsoft.com/en-us/sql/tools/sqlcmd-utility?view=sql-server-ver16#syntax[sqlcmd Utility Syntax]. + +.Login with sqlcmd +[source,shell] +---- +sqlcmd -S localhost -U SA +---- + +[source,shell] +---- +1> SELECT name from sys.databases +2> GO +name +-------------------------------------------------------------------------------------------------------------------------------- +master +tempdb +model +msdb +tpcc + +(5 rows affected) +---- + + +`GO` is required here to execute the previous statements. + +To exit `sqlcmd`, input `quit` or `exit`: + + +The full `sqlcmd` documentation can be found at https://docs.microsoft.com/en-us/sql/tools/sqlcmd-utility?view=sql-server-ver16[sqlcmd Utility]. + +=== Azure Data Studio + +Azure Data Studio is a lightweight, cross-platform data management and development tool with connectivity to popular cloud and on-premises databases. +Azure Data Studio supports Linux, with immediate capability to connect to Azure SQL and SQL Server. +https://learn.microsoft.com/en-us/azure-data-studio/what-is-azure-data-studio[What is Azure Data Studio?] + +Download the `Azure Data Studio` rpm from https://learn.microsoft.com/en-us/azure-data-studio/download-azure-data-studio?view=sql-server-ver16&tabs=linux-install%2Cwin-user-install%2Csuse-install%2Cwindows-uninstall%2Credhat-uninstall#download-azure-data-studio[Download Azure Data Studio] +[source,shell] +---- +curl --location --request GET 'https://go.microsoft.com/fwlink/?linkid=2282380' --output azure-data-studio.rpm +---- + +.Install Azure Data Studio using .rpm +[source,shell] +---- +zypper install .rpm +---- + +.Starting Azure Data Studio run the command on your shell +[source,shell] +---- +azuredatastudio +---- + +image:azure-data-studio.png[Azure Data Studio,480,360,scaledwidth=90%] + +With `Create a connection` the {sqls} can added. A popup window is asking for the required parameter. The connection can be established to a single node or the virtual IP of a cluster setup. + +image:azure-data-studio-connection.png[Azure Data Studio with a connected system,320,240,scaledwidth=90%] + +== Administration + +=== `systemd` + +The `mssql-server` package installs and configures SQL Server as a https://systemd.io/[systemd] service. +`systemd` provides a framework for managing services, mounts, and system states. +You can find more details about `systemd` unit files at https://www.freedesktop.org/software/systemd/man/systemd.unit.html[systemd.unit — Unit configuration]. +To control the `mssql-server` service, use `systemctl` to retrieve the `status`, `start`, `stop`, `restart`, `enable`, and `disable` the service. + +.Display `mssql-server` status as root user +[source,shell] +---- +systemctl status mssql-server.service +● mssql-server.service - Microsoft SQL Server Database Engine + Loaded: loaded (/usr/lib/systemd/system/mssql-server.service; enabled; preset: disabled) + Active: active (running) since Mon 2024-11-11 11:05:43 CET; 1 week 0 days ago + Docs: https://docs.microsoft.com/en-us/sql/linux + Main PID: 23061 (sqlservr) + Tasks: 195 + CPU: 3h 18min 15.202s + CGroup: /system.slice/mssql-server.service + ├─23061 /opt/mssql/bin/sqlservr + └─23066 /opt/mssql/bin/sqlservr + +Nov 11 11:05:58 mssql sqlservr[23066]: [75B blob data] +Nov 11 11:05:58 mssql sqlservr[23066]: [96B blob data] +Nov 11 11:05:58 mssql sqlservr[23066]: [100B blob data] +Nov 11 11:05:58 mssql sqlservr[23066]: [71B blob data] +Nov 11 11:05:58 mssql sqlservr[23066]: [124B blob data] +Nov 11 11:05:59 mssql sqlservr[23066]: [157B blob data] +Nov 11 11:05:59 mssql sqlservr[23066]: [193B blob data] +Nov 11 11:05:59 mssql sqlservr[23066]: [155B blob data] +Nov 11 11:05:59 mssql sqlservr[23066]: [204B blob data] +Nov 11 12:05:49 mssql sqlservr[23066]: [97B blob data] +---- + +.Start `mssql-server` as root user +[source,shell] +---- +systemctl start mssql-server +---- + +.Stop `mssql-server` as root user +[source,shell] +---- +systemctl stop mssql-server +---- + +.Restart `mssql-server` as root user +[source,shell] +---- +systemctl restart mssql-server +---- + +.Enable `mssql-server` to start on boot (`mssql-server` is enabled by default on installation) +[source,shell] +---- +systemctl enable mssql-server + +Created symlink from /etc/systemd/system/multi-user.target.wants/mssql-server.service to /usr/lib/systemd/system/mssql-server.service. +---- + +.Disable `mssql-server` to present starting on boot +[source,shell] +---- +systemctl disable mssql-server + +Removed symlink /etc/systemd/system/multi-user.target.wants/mssql-server.service. +---- + +.Check the `journalctl` log for `mssql-server.service` +[source,shell] +---- +journalctl -fu mssql-server.service +---- + +The parameter `-f` is to follow the log entries. If a static non updates list is preferred just use `journalctl -u mssql-server.service` + +.Check if the network port is active as root user +[source,shell] +---- +ss -tulpan |grep 1433 +---- + +=== Logs + +For troubleshooting, the logs and crash dumps are written to `/var/opt/mssql/log` by default. +Notable logs are the *errorlogs* (+errorlog*+), *trace logs* (+*.trc+), *sqlagent logs* (+sqlagent*+), +and the *extended events logs* (*.xel). Core dumps are written with the `.tar.gz2` extension and SQL dumps with the `.mdmp` extension. +To view these resources, you need `root` or the `mssql` user access. + +[source,shell] +---- +ls /var/opt/mssql/log +errorlog errorlog.6 HkEngineEventFile_0_133741652559190000.xel log_5.trc system_health_0_133736403350200000.xel system_health_0_133752031587310000.xel +errorlog.1 FDLAUNCHERRORLOG HkEngineEventFile_0_133742310585270000.xel log_6.trc system_health_0_133736403551080000.xel system_health_0_133753552568770000.xel +errorlog.2 HkEngineEventFile_0_133736403215340000.xel HkEngineEventFile_0_133752031521550000.xel log_7.trc system_health_0_133740616123760000.xel system_health_0_133757931534220000.xel +errorlog.3 HkEngineEventFile_0_133736403466300000.xel HkEngineEventFile_0_133753552495030000.xel log_8.trc system_health_0_133741585411750000.xel +errorlog.4 HkEngineEventFile_0_133740616015550000.xel HkEngineEventFile_0_133757931472470000.xel mssql-conf system_health_0_133741652635900000.xel +errorlog.5 HkEngineEventFile_0_133741585328790000.xel log_4.trc sqlagentstartup.log system_health_0_133742310655250000.xel +---- + +=== {sqls} starting issues + +If the database doesn't start, check the `journalctl -u mssql-server.service` logs. If the example below is shown, verify the rigth ownership for the directories and files. + +[source,shell] +---- +systemd[1]: mssql-server.service: Main process exited, code=exited, status=229/SELINUX_CONTEXT +... +systemd[1]: mssql-server.service: Main process exited, code=exited, status=229 +---- + +Check the ownership for the files in /data, /tempdb and /log → all of them must be owned by mssql (UID and GID). + +=== Loading sample data + +Microsoft has provided some https://github.com/microsoft/sql-server-samples[sample databases] +you can use to seed your `mssql-server` instance with some data. + +Here is an example of loading our SQL server instance with the sample database `WideWorldImporters`. + +Download the `WideWorldImporters` database: + +[source,shell] +---- +curl --location https://github.com/Microsoft/sql-server-samples/releases/download/wide-world-importers-v1.0/WideWorldImporters-Full.bak \ + --output /tmp/WideWorldImporters-Full.bak +---- + +Restore full backup into `mssql-server` with `sqlcmd` while updating paths for the data, userdata, transaction log, and in-memory data: +(Adapt the password and storage location to your setup) + +[source,sql] +---- +sqlcmd -S localhost \ + -U sa \ + -P Strong\!Passw0rd \ + -Q "RESTORE DATABASE WideWorldImporters \ + FROM DISK ='/tmp/WideWorldImporters-Full.bak' WITH \ + MOVE 'WWI_Primary' TO '/data/WideWorldImporters.mdf', \ + MOVE 'WWI_UserData' TO '/data/WideWorldImporters_UserData.ndf', \ + MOVE 'WWI_Log' TO '/data/WideWorldImporters.ldf', \ + MOVE 'WWI_InMemory_Data_1' TO '/data/WideWorldImporters_InMemory_Data_1'" + +Processed 1464 pages for database 'WideWorldImporters', file 'WWI_Primary' on file 1. +Processed 53096 pages for database 'WideWorldImporters', file 'WWI_UserData' on file 1. +Processed 33 pages for database 'WideWorldImporters', file 'WWI_Log' on file 1. +Processed 3862 pages for database 'WideWorldImporters', file 'WWI_InMemory_Data_1' on file 1. +Converting database 'WideWorldImporters' from version 852 to the current version 904. +Database 'WideWorldImporters' running the upgrade step from version 852 to version 853. +Database 'WideWorldImporters' running the upgrade step from version 853 to version 854. +... +Database 'WideWorldImporters' running the upgrade step from version 902 to version 903. +Database 'WideWorldImporters' running the upgrade step from version 903 to version 904. +RESTORE DATABASE successfully processed 58455 pages in 37.388 seconds (12.214 MB/sec). +---- + +When loaded, project ten table names from the `WideWorldImporters` database to test it out: + +[source,sql] +---- +sqlcmd -S localhost \ + -U sa \ + -P Strong\!Passw0rd \ + -Q "SELECT TOP(10) table_name FROM \ + WideWorldImporters.information_schema.tables \ + WHERE table_type = 'BASE TABLE'" + +table_name +-------------------------------------------------------------------------------------------------------------------------------- + +Colors +Colors_Archive +OrderLines +PackageTypes +PackageTypes_Archive +StockGroups +StockItemStockGroups +StockGroups_Archive +StateProvinces +CustomerTransactions + +(10 rows affected) +---- + +== Summary + +Businesses around the world look to SUSE to help them simplify and optimize their IT environments, +modernize their applications and infrastructure, and accelerate innovation on-premises, in the cloud, and at the edge. +With {sles} support for Microsoft SQL Server, businesses can streamline their IT landscape and operations +without changing their preferred enterprise database management system. + +At this point, you should have a rudimentary understanding of how to install SQL Server on {sles}, +install SQL Server tools, query SQL Server and perform basic administration. +To stay up to date on the latest SQL Server on Linux features bookmark https://docs.microsoft.com/en-us/sql/linux/sql-server-linux-release-notes-2022?view=sql-server-ver16[Release notes for SQL Server 2022 on Linux]. + + +== Appendix + +[id="password_requirements"] +=== SQL Server password requirements + +Password complexity policies are designed to deter brute force attacks by increasing the number of possible passwords. When password complexity policy is enforced, new passwords must meet the following guidelines: +* The password doesn't contain the account name of the user. +* The password is at least eight characters long. +* The password contains characters from three of the following four categories: +** Latin uppercase letters (A through Z) +** Latin lowercase letters (a through z) +** Base 10 digits (0 through 9) +** Nonalphanumeric characters such as: exclamation point (!), dollar sign ($), number sign (#), or percent (%). + +Passwords can be up to 128 characters long. Use passwords that are as long and complex as possible. + +=== Security limitations for SQL Server on Linux + +SQL Server on Linux currently has the following limitations: +* A standard password policy is provided. `MUST_CHANGE` is the only option you might configure. The `CHECK_POLICY` option isn't supported. +* Extensible Key Management isn't supported. +* SQL Server authentication mode can't be disabled. +* Password expiration is hard-coded to 90 days if you use SQL Server authentication. +* Using keys stored in the Azure Key Vault isn't supported. +* SQL Server generates its own self-signed certificate for encrypting connections. SQL Server can be configured to use a user provided certificate for TLS. + +Read more https://learn.microsoft.com/en-us/sql/linux/sql-server-linux-security-overview?view=sql-server-ver16 +and https://learn.microsoft.com/en-us/sql/t-sql/statements/alter-login-transact-sql?view=sql-server-ver16 + +=== Disable the sa account as a best practice + +Please follow the instruction from Microsoft: +https://learn.microsoft.com/en-us/sql/linux/quickstart-install-connect-suse?view=sql-server-linux-ver16#disable-the-sa-account-as-a-best-practice[Disable SA user] + +=== Virtual machines and dynamic memory + +If you're running {sqls} on Linux in a virtual machine, make sure you select options to fix the amount of memory reserved for the virtual machine. Don't use features like Hyper-V Dynamic Memory. +The feature for KVM is called memballoon and can be set to none in the VM configuration. The default is virtio. + +.KVM memballoon +[source,shell] +---- +virsh edit --domain mssql +... + +
+ +... +---- + +The VM must be powered off to activate the changes. A reboot is not enough. + +.before +[source,shell] +---- +lspci |grep balloon + +05:00.0 Unclassified device [00ff]: Red Hat, Inc. Virtio 1.0 memory balloon (rev 01) +---- + +.after +[source,shell] +---- +lspci |grep balloon +---- + +=== References + +* https://documentation.suse.com/sles/15-SP6/[SUSE Linux Enterprise Server 15 SP6] +* https://documentation.suse.com/suma/5.0/[SUSE Manager 5.0 Documentation] +* https://documentation.suse.com/sles/15-SP6/single-html/SLES-rmt/#book-rmt[Repository Mirroring Tool Guide] +* https://docs.microsoft.com/en-us/sql/linux/sql-server-linux-setup?view=sql-server-ver16[Installation guidance for SQL Server on Linux] +* https://docs.microsoft.com/en-us/sql/linux/quickstart-install-connect-suse?view=sql-server-ver16[Quickstart: Install SQL Server and create a database on SUSE Linux Enterprise Server] +* https://docs.microsoft.com/en-us/sql/linux/sql-server-linux-configure-mssql-conf?view=sql-server-ver16[Configure SQL Server on Linux with the mssql-conf tool] +* https://docs.microsoft.com/en-us/sql/tools/sqlcmd-utility?view=sql-server-ver16[sqlcmd Utility] +* https://learn.microsoft.com/en-us/sql/relational-databases/security/password-policy?view=sql-server-ver16[Password Policy] +* https://learn.microsoft.com/en-us/sql/linux/sql-server-linux-security-overview?view=sql-server-ver16[Security limitations for SQL Server on Linux] +* https://learn.microsoft.com/en-us/sql/samples/sql-samples-where-are?view=sql-server-ver16[SQL DB samples] +** https://github.com/microsoft/sql-server-samples[sql-server-samples] + + +:leveloffset: 0 +// Standard SUSE Best Practices includes +== Legal notice +include::common_sbp_legal_notice.adoc[] + +++++ + +++++ + +// Standard SUSE Best Practices includes +// include::common_gfdl1.2_i.adoc[] + +:leveloffset: 0 +include::common_gfdl1.2_i.adoc[] diff --git a/images/src/png/azure-data-studio-connection.png b/images/src/png/azure-data-studio-connection.png new file mode 100644 index 00000000..de175ebd Binary files /dev/null and b/images/src/png/azure-data-studio-connection.png differ diff --git a/images/src/png/azure-data-studio.png b/images/src/png/azure-data-studio.png new file mode 100644 index 00000000..a6275492 Binary files /dev/null and b/images/src/png/azure-data-studio.png differ diff --git a/images/src/png/mssql-db-top.png b/images/src/png/mssql-db-top.png new file mode 100644 index 00000000..135dea8e Binary files /dev/null and b/images/src/png/mssql-db-top.png differ diff --git a/images/src/svg/sqlserver.svg b/images/src/svg/sqlserver.svg new file mode 100644 index 00000000..3c895413 --- /dev/null +++ b/images/src/svg/sqlserver.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file