├── .gitignore ├── 02-DeployAndConfigure ├── loaddata │ └── LoadData.ipynb └── verifydeployment │ ├── VerifyDeployment-MI.ipynb │ ├── VerifyDeployment-SS.ipynb │ └── VerifyDeployment.ipynb ├── 04-Performance ├── monitor_and_scale │ ├── dmdbresourcestats.sql │ ├── dmexecrequests.sql │ ├── flushquerystore.sql │ ├── get_service_objective.sql │ ├── modify_service_objective.sql │ ├── ostress.exe │ ├── sqlworkload.cmd │ └── topcustomersales.sql ├── tuning_applications │ ├── order_rating_ddl.sql │ ├── order_rating_insert.cmd │ ├── order_rating_insert.sql │ ├── order_rating_insert_single.cmd │ ├── order_rating_insert_single.sql │ ├── ostress.exe │ ├── sqlrequests.sql │ ├── tlog_io.sql │ └── top_waits.sql └── tuning_recommendations │ ├── query_order_rating.cmd │ └── query_order_rating.sql ├── 05-Availability ├── fg │ ├── app │ │ ├── pom.xml │ │ ├── src │ │ │ ├── main │ │ │ │ └── java │ │ │ │ │ └── com │ │ │ │ │ └── sqldbsamples │ │ │ │ │ └── App.java │ │ │ └── test │ │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── sqldbsamples │ │ │ │ └── AppTest.java │ │ └── target │ │ │ ├── SqlDbSample-1.0.0.jar │ │ │ ├── classes │ │ │ └── com │ │ │ │ └── sqldbsamples │ │ │ │ └── App.class │ │ │ ├── maven-archiver │ │ │ └── pom.properties │ │ │ ├── maven-status │ │ │ └── maven-compiler-plugin │ │ │ │ ├── compile │ │ │ │ └── default-compile │ │ │ │ │ ├── createdFiles.lst │ │ │ │ │ └── inputFiles.lst │ │ │ │ └── testCompile │ │ │ │ └── default-testCompile │ │ │ │ ├── createdFiles.lst │ │ │ │ └── inputFiles.lst │ │ │ ├── surefire-reports │ │ │ ├── TEST-com.sqldbsamples.AppTest.xml │ │ │ └── com.sqldbsamples.AppTest.txt │ │ │ └── test-classes │ │ │ └── com │ │ │ └── sqldbsamples │ │ │ └── AppTest.class │ ├── fg-powershell.ipynb │ └── graphics │ │ ├── newdbenginequery.png │ │ └── splitscreen.png └── ostress.exe ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md └── SECURITY.md /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # TeamCity is a build add-in 131 | _TeamCity* 132 | 133 | # DotCover is a Code Coverage Tool 134 | *.dotCover 135 | 136 | # AxoCover is a Code Coverage Tool 137 | .axoCover/* 138 | !.axoCover/settings.json 139 | 140 | # Visual Studio code coverage results 141 | *.coverage 142 | *.coveragexml 143 | 144 | # NCrunch 145 | _NCrunch_* 146 | .*crunch*.local.xml 147 | nCrunchTemp_* 148 | 149 | # MightyMoose 150 | *.mm.* 151 | AutoTest.Net/ 152 | 153 | # Web workbench (sass) 154 | .sass-cache/ 155 | 156 | # Installshield output folder 157 | [Ee]xpress/ 158 | 159 | # DocProject is a documentation generator add-in 160 | DocProject/buildhelp/ 161 | DocProject/Help/*.HxT 162 | DocProject/Help/*.HxC 163 | DocProject/Help/*.hhc 164 | DocProject/Help/*.hhk 165 | DocProject/Help/*.hhp 166 | DocProject/Help/Html2 167 | DocProject/Help/html 168 | 169 | # Click-Once directory 170 | publish/ 171 | 172 | # Publish Web Output 173 | *.[Pp]ublish.xml 174 | *.azurePubxml 175 | # Note: Comment the next line if you want to checkin your web deploy settings, 176 | # but database connection strings (with potential passwords) will be unencrypted 177 | *.pubxml 178 | *.publishproj 179 | 180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 181 | # checkin your Azure Web App publish settings, but sensitive information contained 182 | # in these scripts will be unencrypted 183 | PublishScripts/ 184 | 185 | # NuGet Packages 186 | *.nupkg 187 | # NuGet Symbol Packages 188 | *.snupkg 189 | # The packages folder can be ignored because of Package Restore 190 | **/[Pp]ackages/* 191 | # except build/, which is used as an MSBuild target. 192 | !**/[Pp]ackages/build/ 193 | # Uncomment if necessary however generally it will be regenerated when needed 194 | #!**/[Pp]ackages/repositories.config 195 | # NuGet v3's project.json files produces more ignorable files 196 | *.nuget.props 197 | *.nuget.targets 198 | 199 | # Microsoft Azure Build Output 200 | csx/ 201 | *.build.csdef 202 | 203 | # Microsoft Azure Emulator 204 | ecf/ 205 | rcf/ 206 | 207 | # Windows Store app package directories and files 208 | AppPackages/ 209 | BundleArtifacts/ 210 | Package.StoreAssociation.xml 211 | _pkginfo.txt 212 | *.appx 213 | *.appxbundle 214 | *.appxupload 215 | 216 | # Visual Studio cache files 217 | # files ending in .cache can be ignored 218 | *.[Cc]ache 219 | # but keep track of directories ending in .cache 220 | !?*.[Cc]ache/ 221 | 222 | # Others 223 | ClientBin/ 224 | ~$* 225 | *~ 226 | *.dbmdl 227 | *.dbproj.schemaview 228 | *.jfm 229 | *.pfx 230 | *.publishsettings 231 | orleans.codegen.cs 232 | 233 | # Including strong name files can present a security risk 234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 235 | #*.snk 236 | 237 | # Since there are multiple workflows, uncomment next line to ignore bower_components 238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 239 | #bower_components/ 240 | 241 | # RIA/Silverlight projects 242 | Generated_Code/ 243 | 244 | # Backup & report files from converting an old project file 245 | # to a newer Visual Studio version. Backup files are not needed, 246 | # because we have git ;-) 247 | _UpgradeReport_Files/ 248 | Backup*/ 249 | UpgradeLog*.XML 250 | UpgradeLog*.htm 251 | ServiceFabricBackup/ 252 | *.rptproj.bak 253 | 254 | # SQL Server files 255 | *.mdf 256 | *.ldf 257 | *.ndf 258 | 259 | # Business Intelligence projects 260 | *.rdl.data 261 | *.bim.layout 262 | *.bim_*.settings 263 | *.rptproj.rsuser 264 | *- [Bb]ackup.rdl 265 | *- [Bb]ackup ([0-9]).rdl 266 | *- [Bb]ackup ([0-9][0-9]).rdl 267 | 268 | # Microsoft Fakes 269 | FakesAssemblies/ 270 | 271 | # GhostDoc plugin setting file 272 | *.GhostDoc.xml 273 | 274 | # Node.js Tools for Visual Studio 275 | .ntvs_analysis.dat 276 | node_modules/ 277 | 278 | # Visual Studio 6 build log 279 | *.plg 280 | 281 | # Visual Studio 6 workspace options file 282 | *.opt 283 | 284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 285 | *.vbw 286 | 287 | # Visual Studio LightSwitch build output 288 | **/*.HTMLClient/GeneratedArtifacts 289 | **/*.DesktopClient/GeneratedArtifacts 290 | **/*.DesktopClient/ModelManifest.xml 291 | **/*.Server/GeneratedArtifacts 292 | **/*.Server/ModelManifest.xml 293 | _Pvt_Extensions 294 | 295 | # Paket dependency manager 296 | .paket/paket.exe 297 | paket-files/ 298 | 299 | # FAKE - F# Make 300 | .fake/ 301 | 302 | # CodeRush personal settings 303 | .cr/personal 304 | 305 | # Python Tools for Visual Studio (PTVS) 306 | __pycache__/ 307 | *.pyc 308 | 309 | # Cake - Uncomment if you are using it 310 | # tools/** 311 | # !tools/packages.config 312 | 313 | # Tabs Studio 314 | *.tss 315 | 316 | # Telerik's JustMock configuration file 317 | *.jmconfig 318 | 319 | # BizTalk build output 320 | *.btp.cs 321 | *.btm.cs 322 | *.odx.cs 323 | *.xsd.cs 324 | 325 | # OpenCover UI analysis results 326 | OpenCover/ 327 | 328 | # Azure Stream Analytics local run output 329 | ASALocalRun/ 330 | 331 | # MSBuild Binary and Structured Log 332 | *.binlog 333 | 334 | # NVidia Nsight GPU debugger configuration file 335 | *.nvuser 336 | 337 | # MFractors (Xamarin productivity tool) working folder 338 | .mfractor/ 339 | 340 | # Local History for Visual Studio 341 | .localhistory/ 342 | 343 | # BeatPulse healthcheck temp database 344 | healthchecksdb 345 | 346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 347 | MigrationBackup/ 348 | 349 | # Ionide (cross platform F# VS Code tools) working folder 350 | .ionide/ 351 | -------------------------------------------------------------------------------- /02-DeployAndConfigure/loaddata/LoadData.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "kernelspec": { 4 | "name": "SQL", 5 | "display_name": "SQL", 6 | "language": "sql" 7 | }, 8 | "language_info": { 9 | "name": "sql", 10 | "version": "" 11 | } 12 | }, 13 | "nbformat_minor": 2, 14 | "nbformat": 4, 15 | "cells": [ 16 | { 17 | "cell_type": "markdown", 18 | "source": [ 19 | "# Load data - Azure SQL Database\r\n", 20 | "\r\n", 21 | "In this activity, you'll get to see how you can bulk load data into Azure SQL Database. \r\n", 22 | "\r\n", 23 | "\r\n", 24 | "**Set up - Attach the notebook to Azure SQL Database** \r\n", 25 | "\r\n", 26 | "0. You should have opened this file using Azure Data Studio. If you didn't, please refer to Module 2 Activity 3 in the main Module 2 file to get set up. \r\n", 27 | "1. In the bar at the top of this screen, confirm or change the \"Kernel\" to **SQL**. This determines what language the code blocks in the file are. In this case, that language is SQL. \r\n", 28 | "2. For \"Attach to\", use the drop-down to select **Change Connection**. From the Recent Connections pane, you should be able to select your Azure SQL Database logical server and be sure to **select your AdventureWorks database as the database to connect to**. \r\n", 29 | "\r\n", 30 | "Now that you're set up, you should read the text cells and \"Run\" the code cells by selecting the play button that appears in the left of a code cell when you hover over it. \r\n", 31 | "> Some of the cells have been run before, this is just to show you the expected result from the testing of the labs. If you choose not to complete the labs/prerequisites, do not run any cells, just review the results. \r\n", 32 | "" 33 | ], 34 | "metadata": { 35 | "azdata_cell_guid": "2c06b521-aaf9-41a8-9824-f06a3fb12e2c" 36 | } 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "source": [ 41 | "When you're bulk loading data, it has to come from somewhere. In Azure, it's very common to store or dump data into an [Azure Blob Storage](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction) because Blob storage is optimized for storing massive amounts of unstructured data at a relatively low cost. \r\n", 42 | "\r\n", 43 | "In this scenario, AdventureWorks is receiving store return data based on store identification number (e.g. 1, 2, etc.) This return data is being stored in `.dat` files which are then pushed into Azure Blob storage. \r\n", 44 | "\r\n", 45 | "Within blob storage, there exists three types of resources: \r\n", 46 | "* Storage account: this provides a unique namespace for a storage account, and a way to connect or access it \r\n", 47 | "* Containers: these are used to organize a set of blobs. A storage account can have an unlimited number of containers \r\n", 48 | "* Blobs: there are several types of blobs but we will use Block blobs that can store text and binary data that can be managed individually. \r\n", 49 | "\r\n", 50 | "Now, once the data is in blob storage, Azure SQL needs a way to access it. You can do that by [creating an external data source](https://docs.microsoft.com/en-us/sql/t-sql/statements/create-external-data-source-transact-sql?view=azuresqldb-current) that has access to the Azure Storage account. \r\n", 51 | "\r\n", 52 | "You can [control access to Azure Storage accounts](https://docs.microsoft.com/en-us/azure/storage/common/storage-account-overview?toc=%2fazure%2fstorage%2fblobs%2ftoc.json#control-access-to-account-data) through Azure Active Directory, Shared Key authorization, or with a Shared access signature (SAS). The link points to more details, but we will use SAS for this exercise. \r\n", 53 | "\r\n", 54 | "If you want to read more about how SAS works with regards to Azure Storage, please [read here](https://docs.microsoft.com/en-us/azure/storage/common/storage-sas-overview) before continuing. \r\n", 55 | "\r\n", 56 | "" 57 | ], 58 | "metadata": { 59 | "azdata_cell_guid": "8cdf43ef-a2ce-42b1-af4c-4cb2669440f3" 60 | } 61 | }, 62 | { 63 | "cell_type": "markdown", 64 | "source": [ 65 | "**Step 1 - Create a table and schema** \r\n", 66 | "\r\n", 67 | "First, we need to create a table and schema for our data to be loaded into. This is pretty straightforward, good old-fashioned T-SQL." 68 | ], 69 | "metadata": { 70 | "azdata_cell_guid": "234764b7-3174-401f-b105-66f22bee5ab3" 71 | } 72 | }, 73 | { 74 | "cell_type": "code", 75 | "source": [ 76 | "IF SCHEMA_ID('DataLoad') IS NULL \r\n", 77 | "EXEC ('CREATE SCHEMA DataLoad')\r\n", 78 | "\r\n", 79 | "CREATE TABLE DataLoad.store_returns\r\n", 80 | "(\r\n", 81 | " sr_returned_date_sk bigint,\r\n", 82 | " sr_return_time_sk bigint,\r\n", 83 | " sr_item_sk bigint ,\r\n", 84 | " sr_customer_sk bigint,\r\n", 85 | " sr_cdemo_sk bigint,\r\n", 86 | " sr_hdemo_sk bigint,\r\n", 87 | " sr_addr_sk bigint,\r\n", 88 | " sr_store_sk bigint,\r\n", 89 | " sr_reason_sk bigint,\r\n", 90 | " sr_ticket_number bigint ,\r\n", 91 | " sr_return_quantity integer,\r\n", 92 | " sr_return_amt float,\r\n", 93 | " sr_return_tax float,\r\n", 94 | " sr_return_amt_inc_tax float,\r\n", 95 | " sr_fee float,\r\n", 96 | " sr_return_ship_cost float,\r\n", 97 | " sr_refunded_cash float,\r\n", 98 | " sr_reversed_charge float,\r\n", 99 | " sr_store_credit float,\r\n", 100 | " sr_net_loss float\r\n", 101 | "\r\n", 102 | ") " 103 | ], 104 | "metadata": { 105 | "azdata_cell_guid": "46df44da-7cb9-48c1-b071-fee30b67d4d1" 106 | }, 107 | "outputs": [ 108 | { 109 | "output_type": "display_data", 110 | "data": { 111 | "text/html": "Commands completed successfully." 112 | }, 113 | "metadata": {} 114 | }, 115 | { 116 | "output_type": "display_data", 117 | "data": { 118 | "text/html": "Total execution time: 00:00:00.102" 119 | }, 120 | "metadata": {} 121 | } 122 | ], 123 | "execution_count": 1 124 | }, 125 | { 126 | "cell_type": "markdown", 127 | "source": [ 128 | "**Step 2 - Create a `MASTER KEY`** \r\n", 129 | "\r\n", 130 | "Leveraging [an example in the docs](https://docs.microsoft.com/en-us/sql/t-sql/statements/bulk-insert-transact-sql?view=sql-server-ver15#f-importing-data-from-a-file-in-azure-blob-storage) you learn that a `MASTER KEY` is required to create a `DATABASE SCOPED CREDENTIAL` since the blob storage is not configured to allow public (anonymous) access. \r\n", 131 | "\r\n", 132 | "So, let's first create a `MASTER KEY`" 133 | ], 134 | "metadata": { 135 | "azdata_cell_guid": "c66497ba-8fc8-4296-829e-562ccc6a942b" 136 | } 137 | }, 138 | { 139 | "cell_type": "code", 140 | "source": [ 141 | "CREATE MASTER KEY \r\n", 142 | "ENCRYPTION BY PASSWORD='MyComplexPassword00!';" 143 | ], 144 | "metadata": { 145 | "azdata_cell_guid": "65b4c01a-9bec-417b-a471-4b99c4e28cea" 146 | }, 147 | "outputs": [ 148 | { 149 | "output_type": "display_data", 150 | "data": { 151 | "text/html": "Commands completed successfully." 152 | }, 153 | "metadata": {} 154 | }, 155 | { 156 | "output_type": "display_data", 157 | "data": { 158 | "text/html": "Total execution time: 00:00:00.093" 159 | }, 160 | "metadata": {} 161 | } 162 | ], 163 | "execution_count": 2 164 | }, 165 | { 166 | "cell_type": "markdown", 167 | "source": [ 168 | "**Step 3 - Create a `DATABASE SCOPED CREDENTIAL`**\n", 169 | "\n", 170 | "A `MASTER KEY` is required to create a `DATABASE SCOPED CREDENTIAL`, which we can now create. The credential refers to the Azure blob storage account and the `data/` portion specifies the container where the store return data is located.\n", 171 | "\n", 172 | "We use `SHARED ACCESS SIGNATURE` as the identity which SQL knows how to interpret, and the secret provided is the SAS token that you can generate from the Azure blob storage account.\n", 173 | "\n", 174 | "> Note: the `?` at the beginning of the SAS token should be removed" 175 | ], 176 | "metadata": { 177 | "azdata_cell_guid": "68c55330-e433-4526-a62f-904660fb8adb" 178 | } 179 | }, 180 | { 181 | "cell_type": "code", 182 | "source": [ 183 | "CREATE DATABASE SCOPED CREDENTIAL [https://azuresqlworkshopsa.blob.core.windows.net/data/]\r\n", 184 | "WITH IDENTITY = 'SHARED ACCESS SIGNATURE',\r\n", 185 | "SECRET = 'st=2020-09-28T22%3A05%3A27Z&se=2030-09-29T22%3A05%3A00Z&sp=rl&sv=2018-03-28&sr=c&sig=52WbuSIJCWyjS6IW6W0ILfIpqh4wLMXmOlifPyOetZI%3D';" 186 | ], 187 | "metadata": { 188 | "azdata_cell_guid": "26c0a508-595d-4ead-a680-b8ea422a8d68", 189 | "tags": [] 190 | }, 191 | "outputs": [ 192 | { 193 | "output_type": "display_data", 194 | "data": { 195 | "text/html": "Commands completed successfully." 196 | }, 197 | "metadata": {} 198 | }, 199 | { 200 | "output_type": "display_data", 201 | "data": { 202 | "text/html": "Total execution time: 00:00:00.089" 203 | }, 204 | "metadata": {} 205 | } 206 | ], 207 | "execution_count": 3 208 | }, 209 | { 210 | "cell_type": "markdown", 211 | "source": [ 212 | "**Step 4 - Create an external data source to the container** \r\n", 213 | "\r\n", 214 | "> Note: `LOCATION` doesn't have a trailing `/`, even through the `CREDENTIAL` does." 215 | ], 216 | "metadata": { 217 | "azdata_cell_guid": "3e65516c-6c05-4cc4-b8f4-310d9fe41da2" 218 | } 219 | }, 220 | { 221 | "cell_type": "code", 222 | "source": [ 223 | "CREATE EXTERNAL DATA SOURCE dataset\r\n", 224 | "WITH \r\n", 225 | "(\r\n", 226 | " TYPE = BLOB_STORAGE,\r\n", 227 | " LOCATION = 'https://azuresqlworkshopsa.blob.core.windows.net/data',\r\n", 228 | " CREDENTIAL = [https://azuresqlworkshopsa.blob.core.windows.net/data/]\r\n", 229 | ");" 230 | ], 231 | "metadata": { 232 | "azdata_cell_guid": "e8e3ad86-2f58-41ef-a568-18ffc9128438" 233 | }, 234 | "outputs": [ 235 | { 236 | "output_type": "display_data", 237 | "data": { 238 | "text/html": "Commands completed successfully." 239 | }, 240 | "metadata": {} 241 | }, 242 | { 243 | "output_type": "display_data", 244 | "data": { 245 | "text/html": "Total execution time: 00:00:00.086" 246 | }, 247 | "metadata": {} 248 | } 249 | ], 250 | "execution_count": 4 251 | }, 252 | { 253 | "cell_type": "markdown", 254 | "source": [ 255 | "**Step 5 - `BULK INSERT` a single file** \r\n", 256 | "\r\n", 257 | "You're finally ready to `BULK INSERT` one of the store return files. \r\n", 258 | "\r\n", 259 | "Run the following cell, and while it completes, review the comments." 260 | ], 261 | "metadata": { 262 | "azdata_cell_guid": "7d0ffa7d-660a-48c1-aa6b-2a295aff2e30" 263 | } 264 | }, 265 | { 266 | "cell_type": "code", 267 | "source": [ 268 | "SET NOCOUNT ON -- Reduce network traffic by stopping the message that shows the number of rows affected\r\n", 269 | " BULK INSERT DataLoad.store_returns -- Table you created in Step 1\r\n", 270 | " FROM 'dataset/store_returns/store_returns_1.dat' -- Within the container, the location of the file\r\n", 271 | " WITH (\r\n", 272 | "\t\t\tDATA_SOURCE = 'dataset' -- Using the External data source from Step 4\r\n", 273 | "\t\t\t,DATAFILETYPE = 'char' \r\n", 274 | "\t ,FIELDTERMINATOR = '\\|' \r\n", 275 | "\t ,ROWTERMINATOR = '\\|\\n' \r\n", 276 | " ,BATCHSIZE=100000 -- Reduce network traffic by inserting in batches\r\n", 277 | " , TABLOCK -- Minimize number of log records for the insert operation\r\n", 278 | " )" 279 | ], 280 | "metadata": { 281 | "azdata_cell_guid": "bcc16f9e-1fc5-4f51-8cd2-11d47da4b24d" 282 | }, 283 | "outputs": [ 284 | { 285 | "output_type": "display_data", 286 | "data": { 287 | "text/html": "Commands completed successfully." 288 | }, 289 | "metadata": {} 290 | }, 291 | { 292 | "output_type": "display_data", 293 | "data": { 294 | "text/html": "Total execution time: 00:01:28.408" 295 | }, 296 | "metadata": {} 297 | } 298 | ], 299 | "execution_count": 5 300 | }, 301 | { 302 | "cell_type": "markdown", 303 | "source": [ 304 | "For now, let's check how many rows were inserted into our table:" 305 | ], 306 | "metadata": { 307 | "azdata_cell_guid": "96f0dcbb-7bf6-456e-b5d8-53763eae3630" 308 | } 309 | }, 310 | { 311 | "cell_type": "code", 312 | "source": [ 313 | "select count(*) from DataLoad.store_returns" 314 | ], 315 | "metadata": { 316 | "azdata_cell_guid": "36c0c58f-b0a1-4854-88d1-e576e31b37d0", 317 | "tags": [] 318 | }, 319 | "outputs": [ 320 | { 321 | "output_type": "display_data", 322 | "data": { 323 | "text/html": "Commands completed successfully." 324 | }, 325 | "metadata": {} 326 | }, 327 | { 328 | "output_type": "display_data", 329 | "data": { 330 | "text/html": "Total execution time: 00:00:00.928" 331 | }, 332 | "metadata": {} 333 | }, 334 | { 335 | "output_type": "execute_result", 336 | "metadata": {}, 337 | "execution_count": 6, 338 | "data": { 339 | "application/vnd.dataresource+json": { 340 | "schema": { 341 | "fields": [ 342 | { 343 | "name": "(No column name)" 344 | } 345 | ] 346 | }, 347 | "data": [ 348 | { 349 | "0": "2807797" 350 | } 351 | ] 352 | }, 353 | "text/html": [ 354 | "", 355 | "", 356 | "", 357 | "
(No column name)
2807797
" 358 | ] 359 | } 360 | } 361 | ], 362 | "execution_count": 6 363 | }, 364 | { 365 | "cell_type": "markdown", 366 | "source": [ 367 | "If you want to run throught the exercise again, run the following code to reset what you've done." 368 | ], 369 | "metadata": { 370 | "azdata_cell_guid": "3ab4cac4-9c02-4ee1-818d-c6cbaa54ca6e" 371 | } 372 | }, 373 | { 374 | "cell_type": "code", 375 | "source": [ 376 | "DROP EXTERNAL DATA SOURCE dataset\r\n", 377 | "DROP DATABASE SCOPED CREDENTIAL [https://azuresqlworkshopsa.blob.core.windows.net/data/]\r\n", 378 | "DROP TABLE DataLoad.store_returns\r\n", 379 | "DROP MASTER KEY" 380 | ], 381 | "metadata": { 382 | "azdata_cell_guid": "297d59bb-08be-4680-94e4-028161ac0b4e" 383 | }, 384 | "outputs": [ 385 | { 386 | "output_type": "display_data", 387 | "data": { 388 | "text/html": "Commands completed successfully." 389 | }, 390 | "metadata": {} 391 | }, 392 | { 393 | "output_type": "display_data", 394 | "data": { 395 | "text/html": "Total execution time: 00:00:00.093" 396 | }, 397 | "metadata": {} 398 | } 399 | ], 400 | "execution_count": 11 401 | }, 402 | { 403 | "cell_type": "markdown", 404 | "source": [ 405 | "You've seen how you can optimize bulk inserts in this activity. We are really just skimming the surface here, and in the Performance module you'll learn about other ways you can optimize performance. You can also check the [documentation (under **How to** > **Load and move data**)](https://docs.microsoft.com/en-us/azure/sql-database/sql-database-load-from-csv-with-bcp) for more information. " 406 | ], 407 | "metadata": { 408 | "azdata_cell_guid": "ece2733b-4152-4e47-90ea-cda0da0882cb" 409 | } 410 | } 411 | ] 412 | } -------------------------------------------------------------------------------- /04-Performance/monitor_and_scale/dmdbresourcestats.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM sys.dm_db_resource_stats; 2 | GO -------------------------------------------------------------------------------- /04-Performance/monitor_and_scale/dmexecrequests.sql: -------------------------------------------------------------------------------- 1 | SELECT er.session_id, er.status, er.command, er.wait_type, er.last_wait_type, er.wait_resource, er.wait_time 2 | FROM sys.dm_exec_requests er 3 | INNER JOIN sys.dm_exec_sessions es 4 | ON er.session_id = es.session_id 5 | AND es.is_user_process = 1; 6 | GO -------------------------------------------------------------------------------- /04-Performance/monitor_and_scale/flushquerystore.sql: -------------------------------------------------------------------------------- 1 | EXEC sp_query_store_flush_db; 2 | GO -------------------------------------------------------------------------------- /04-Performance/monitor_and_scale/get_service_objective.sql: -------------------------------------------------------------------------------- 1 | SELECT database_name,slo_name,cpu_limit,max_db_memory, max_db_max_size_in_mb, primary_max_log_rate,primary_group_max_io, volume_local_iops,volume_pfs_iops 2 | FROM sys.dm_user_db_resource_governance; 3 | GO 4 | SELECT DATABASEPROPERTYEX('AdventureWorks', 'ServiceObjective'); 5 | GO 6 | -------------------------------------------------------------------------------- /04-Performance/monitor_and_scale/modify_service_objective.sql: -------------------------------------------------------------------------------- 1 | ALTER DATABASE AdventureWorks MODIFY (SERVICE_OBJECTIVE = 'GP_Gen5_8'); 2 | GO -------------------------------------------------------------------------------- /04-Performance/monitor_and_scale/ostress.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MicrosoftDocs/mslearn-azure-sql-fundamentals/ad17351bf330631dd22b99642c1064dd073e763b/04-Performance/monitor_and_scale/ostress.exe -------------------------------------------------------------------------------- /04-Performance/monitor_and_scale/sqlworkload.cmd: -------------------------------------------------------------------------------- 1 | ostress.exe -Saw-server.database.windows.net -itopcustomersales.sql -Ucloudadmin -dAdventureWorks -P -n10 -r2 -q -------------------------------------------------------------------------------- /04-Performance/monitor_and_scale/topcustomersales.sql: -------------------------------------------------------------------------------- 1 | DECLARE @x int 2 | DECLARE @y float 3 | SET @x = 0; 4 | WHILE (@x < 10000) 5 | BEGIN 6 | SELECT @y = sum(cast((soh.SubTotal*soh.TaxAmt*soh.TotalDue) as float)) 7 | FROM SalesLT.Customer c 8 | INNER JOIN SalesLT.SalesOrderHeader soh 9 | ON c.CustomerID = soh.CustomerID 10 | INNER JOIN SalesLT.SalesOrderDetail sod 11 | ON soh.SalesOrderID = sod.SalesOrderID 12 | INNER JOIN SalesLT.Product p 13 | ON p.ProductID = sod.ProductID 14 | GROUP BY c.CompanyName 15 | ORDER BY c.CompanyName; 16 | SET @x = @x + 1; 17 | END 18 | GO -------------------------------------------------------------------------------- /04-Performance/tuning_applications/order_rating_ddl.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS SalesLT.OrderRating; 2 | GO 3 | CREATE TABLE SalesLT.OrderRating 4 | (OrderRatingID int identity not null, 5 | SalesOrderID int not null, 6 | OrderRatingDT datetime not null, 7 | OrderRating int not null, 8 | OrderRatingComments char(500) not null); 9 | GO -------------------------------------------------------------------------------- /04-Performance/tuning_applications/order_rating_insert.cmd: -------------------------------------------------------------------------------- 1 | ostress.exe -Saw-server.database.windows.net -iorder_rating_insert.sql -Ucloudadmin -dAdventureWorks -P -n25 -r10 -q -------------------------------------------------------------------------------- /04-Performance/tuning_applications/order_rating_insert.sql: -------------------------------------------------------------------------------- 1 | DECLARE @x int; 2 | SET @x = 0; 3 | BEGIN TRAN; 4 | WHILE (@x < 500) 5 | BEGIN 6 | SET @x = @x + 1; 7 | INSERT INTO SalesLT.OrderRating 8 | (SalesOrderID, OrderRatingDT, OrderRating, OrderRatingComments) 9 | VALUES (@x, getdate(), 5, 'This was a great order'); 10 | END 11 | COMMIT TRAN; 12 | GO -------------------------------------------------------------------------------- /04-Performance/tuning_applications/order_rating_insert_single.cmd: -------------------------------------------------------------------------------- 1 | ostress.exe -Saw-server.database.windows.net -iorder_rating_insert_single.sql -Ucloudadmin -dAdventureWorks -P -n25 -r10 -q -------------------------------------------------------------------------------- /04-Performance/tuning_applications/order_rating_insert_single.sql: -------------------------------------------------------------------------------- 1 | DECLARE @x int; 2 | SET @x = 0; 3 | WHILE (@x < 500) 4 | BEGIN 5 | SET @x = @x + 1; 6 | INSERT INTO SalesLT.OrderRating 7 | (SalesOrderID, OrderRatingDT, OrderRating, OrderRatingComments) 8 | VALUES (@x, getdate(), 5, 'This was a great order'); 9 | END 10 | GO -------------------------------------------------------------------------------- /04-Performance/tuning_applications/ostress.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MicrosoftDocs/mslearn-azure-sql-fundamentals/ad17351bf330631dd22b99642c1064dd073e763b/04-Performance/tuning_applications/ostress.exe -------------------------------------------------------------------------------- /04-Performance/tuning_applications/sqlrequests.sql: -------------------------------------------------------------------------------- 1 | SELECT er.session_id, er.status, er.command, er.wait_type, er.last_wait_type, er.wait_resource, er.wait_time 2 | FROM sys.dm_exec_requests er 3 | INNER JOIN sys.dm_exec_sessions es 4 | ON er.session_id = es.session_id 5 | AND es.is_user_process = 1; 6 | GO -------------------------------------------------------------------------------- /04-Performance/tuning_applications/tlog_io.sql: -------------------------------------------------------------------------------- 1 | SELECT io_stall_write_ms/num_of_writes as avg_tlog_io_write_ms, * 2 | FROM sys.dm_io_virtual_file_stats 3 | (db_id('Adventureworks'), 2); 4 | GO -------------------------------------------------------------------------------- /04-Performance/tuning_applications/top_waits.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM sys.dm_os_wait_stats 2 | ORDER BY waiting_tasks_count DESC; 3 | GO -------------------------------------------------------------------------------- /04-Performance/tuning_recommendations/query_order_rating.cmd: -------------------------------------------------------------------------------- 1 | date /T 2 | time /T 3 | ostress.exe -Saw-server.database.windows.net -iquery_order_rating.sql -Ucloudadmin -dAdventureWorks -P -n25 -r100000 -q 4 | date /T 5 | time /T -------------------------------------------------------------------------------- /04-Performance/tuning_recommendations/query_order_rating.sql: -------------------------------------------------------------------------------- 1 | SELECT * FROM SalesLT.OrderRating 2 | WHERE OrderRatingID = 1; 3 | GO -------------------------------------------------------------------------------- /05-Availability/fg/app/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.sqldbsamples 5 | SqlDbSample 6 | jar 7 | 1.0.0 8 | SqlDbSample 9 | http://maven.apache.org 10 | 11 | 12 | junit 13 | junit 14 | 3.8.1 15 | test 16 | 17 | 18 | com.microsoft.sqlserver 19 | mssql-jdbc 20 | 6.1.0.jre8 21 | 22 | 23 | 24 | 1.8 25 | 1.8 26 | 27 | 28 | 29 | 30 | org.apache.maven.plugins 31 | maven-jar-plugin 32 | 3.0.0 33 | 34 | 35 | 36 | com.sqldbsamples.App 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /05-Availability/fg/app/src/main/java/com/sqldbsamples/App.java: -------------------------------------------------------------------------------- 1 | package com.sqldbsamples; 2 | 3 | import java.sql.Connection; 4 | import java.sql.Statement; 5 | import java.sql.PreparedStatement; 6 | import java.sql.ResultSet; 7 | import java.sql.Timestamp; 8 | import java.sql.DriverManager; 9 | import java.util.Date; 10 | import java.util.concurrent.TimeUnit; 11 | 12 | public class App { 13 | 14 | // UPDATE WITH YOUR INFO 15 | private static final String FAILOVER_GROUP_NAME = "aw-server-fg-ID"; // add workshop ID 16 | // UPDATE WITH YOUR INFO 17 | private static final String DB_NAME = "AdventureWorks"; // add database name 18 | // UPDATE WITH YOUR INFO 19 | private static final String USER = "cloudadmin"; // add database user 20 | // UPDATE WITH YOUR INFO 21 | private static final String PASSWORD = "password"; // add database password 22 | // DO NOT MODIFY 23 | private static final String READ_WRITE_URL = String.format("jdbc:" + 24 | "sqlserver://%s.database.windows.net:1433;database=%s;user=%s;password=%s;encrypt=true;" + 25 | "hostNameInCertificate=*.database.windows.net;loginTimeout=30;", 26 | FAILOVER_GROUP_NAME, DB_NAME, USER, PASSWORD); 27 | private static final String READ_ONLY_URL = String.format("jdbc:" + 28 | "sqlserver://%s.secondary.database.windows.net:1433;database=%s;user=%s;password=%s;encrypt=true;" + 29 | "hostNameInCertificate=*.database.windows.net;loginTimeout=30;", 30 | FAILOVER_GROUP_NAME, DB_NAME, USER, PASSWORD); 31 | 32 | public static void main(String[] args) { 33 | System.out.println("#######################################"); 34 | System.out.println("## GEO DISTRIBUTED DATABASE TUTORIAL ##"); 35 | System.out.println("#######################################"); 36 | System.out.println(""); 37 | 38 | int highWaterMark = getHighWaterMarkId(); 39 | 40 | try { 41 | for(int i = 1; i < 1000; i++) { 42 | // loop will run for about 1 hour 43 | System.out.print(i + ": insert on primary " + 44 | (insertData((highWaterMark + i))?"successful":"failed")); 45 | TimeUnit.SECONDS.sleep(1); 46 | System.out.print(", read from secondary " + 47 | (selectData((highWaterMark + i))?"successful":"failed") + "\n"); 48 | TimeUnit.SECONDS.sleep(3); 49 | } 50 | } catch(Exception e) { 51 | e.printStackTrace(); 52 | } 53 | } 54 | 55 | private static boolean insertData(int id) { 56 | // Insert data into the product table with a unique product name so we can find the product again 57 | String sql = "INSERT INTO SalesLT.Product " + 58 | "(Name, ProductNumber, Color, StandardCost, ListPrice, SellStartDate) VALUES (?,?,?,?,?,?);"; 59 | 60 | try (Connection connection = DriverManager.getConnection(READ_WRITE_URL); 61 | PreparedStatement pstmt = connection.prepareStatement(sql)) { 62 | pstmt.setString(1, "BrandNewProduct" + id); 63 | pstmt.setInt(2, 200989 + id + 10000); 64 | pstmt.setString(3, "Blue"); 65 | pstmt.setDouble(4, 75.00); 66 | pstmt.setDouble(5, 89.99); 67 | pstmt.setTimestamp(6, new Timestamp(new Date().getTime())); 68 | return (1 == pstmt.executeUpdate()); 69 | } catch (Exception e) { 70 | return false; 71 | } 72 | } 73 | 74 | private static boolean selectData(int id) { 75 | // Query the data previously inserted into the primary database from the geo replicated database 76 | String sql = "SELECT Name, Color, ListPrice FROM SalesLT.Product WHERE Name = ?"; 77 | 78 | try (Connection connection = DriverManager.getConnection(READ_ONLY_URL); 79 | PreparedStatement pstmt = connection.prepareStatement(sql)) { 80 | pstmt.setString(1, "BrandNewProduct" + id); 81 | try (ResultSet resultSet = pstmt.executeQuery()) { 82 | return resultSet.next(); 83 | } 84 | } catch (Exception e) { 85 | return false; 86 | } 87 | } 88 | 89 | private static int getHighWaterMarkId() { 90 | // Query the high water mark id stored in the table to be able to make unique inserts 91 | String sql = "SELECT MAX(ProductId) FROM SalesLT.Product"; 92 | int result = 1; 93 | try (Connection connection = DriverManager.getConnection(READ_WRITE_URL); 94 | Statement stmt = connection.createStatement(); 95 | ResultSet resultSet = stmt.executeQuery(sql)) { 96 | if (resultSet.next()) { 97 | result = resultSet.getInt(1); 98 | } 99 | } catch (Exception e) { 100 | e.printStackTrace(); 101 | } 102 | return result; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /05-Availability/fg/app/src/test/java/com/sqldbsamples/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.sqldbsamples; 2 | 3 | import junit.framework.Test; 4 | import junit.framework.TestCase; 5 | import junit.framework.TestSuite; 6 | 7 | /** 8 | * Unit test for simple App. 9 | */ 10 | public class AppTest 11 | extends TestCase 12 | { 13 | /** 14 | * Create the test case 15 | * 16 | * @param testName name of the test case 17 | */ 18 | public AppTest( String testName ) 19 | { 20 | super( testName ); 21 | } 22 | 23 | /** 24 | * @return the suite of tests being tested 25 | */ 26 | public static Test suite() 27 | { 28 | return new TestSuite( AppTest.class ); 29 | } 30 | 31 | /** 32 | * Rigourous Test :-) 33 | */ 34 | public void testApp() 35 | { 36 | assertTrue( true ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /05-Availability/fg/app/target/SqlDbSample-1.0.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MicrosoftDocs/mslearn-azure-sql-fundamentals/ad17351bf330631dd22b99642c1064dd073e763b/05-Availability/fg/app/target/SqlDbSample-1.0.0.jar -------------------------------------------------------------------------------- /05-Availability/fg/app/target/classes/com/sqldbsamples/App.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MicrosoftDocs/mslearn-azure-sql-fundamentals/ad17351bf330631dd22b99642c1064dd073e763b/05-Availability/fg/app/target/classes/com/sqldbsamples/App.class -------------------------------------------------------------------------------- /05-Availability/fg/app/target/maven-archiver/pom.properties: -------------------------------------------------------------------------------- 1 | #Created by Apache Maven 3.6.3 2 | #Thu Feb 06 20:52:45 UTC 2020 3 | version=1.0.0 4 | groupId=com.sqldbsamples 5 | artifactId=SqlDbSample 6 | -------------------------------------------------------------------------------- /05-Availability/fg/app/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst: -------------------------------------------------------------------------------- 1 | com\sqldbsamples\App.class 2 | -------------------------------------------------------------------------------- /05-Availability/fg/app/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst: -------------------------------------------------------------------------------- 1 | C:\Users\antho\SqlDbSample\src\main\java\com\sqldbsamples\App.java 2 | -------------------------------------------------------------------------------- /05-Availability/fg/app/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst: -------------------------------------------------------------------------------- 1 | com\sqldbsamples\AppTest.class 2 | -------------------------------------------------------------------------------- /05-Availability/fg/app/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst: -------------------------------------------------------------------------------- 1 | C:\Users\vmuser\sqlworkshops\AzureSQLWorkshop\azuresqlworkshop\05-Availability\fg\app\src\test\java\com\sqldbsamples\AppTest.java 2 | -------------------------------------------------------------------------------- /05-Availability/fg/app/target/surefire-reports/TEST-com.sqldbsamples.AppTest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /05-Availability/fg/app/target/surefire-reports/com.sqldbsamples.AppTest.txt: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | Test set: com.sqldbsamples.AppTest 3 | ------------------------------------------------------------------------------- 4 | Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.033 sec 5 | -------------------------------------------------------------------------------- /05-Availability/fg/app/target/test-classes/com/sqldbsamples/AppTest.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MicrosoftDocs/mslearn-azure-sql-fundamentals/ad17351bf330631dd22b99642c1064dd073e763b/05-Availability/fg/app/target/test-classes/com/sqldbsamples/AppTest.class -------------------------------------------------------------------------------- /05-Availability/fg/fg-powershell.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "kernelspec": { 4 | "name": "powershell", 5 | "display_name": "PowerShell" 6 | }, 7 | "language_info": { 8 | "name": "powershell", 9 | "codemirror_mode": "shell", 10 | "mimetype": "text/x-sh", 11 | "file_extension": ".ps1" 12 | } 13 | }, 14 | "nbformat_minor": 2, 15 | "nbformat": 4, 16 | "cells": [ 17 | { 18 | "cell_type": "markdown", 19 | "source": [ 20 | "# Activity 4: Creating failover groups using PowerShell \r\n", 21 | "\r\n", 22 | "#### The Azure SQL Workshop - Module 5\r\n", 23 | "\r\n", 24 | "

\r\n", 25 | "\r\n", 26 | "In the module, you learned about geo-replication and auto-failover groups. In this activity, you'll configure auto-failover groups for your Azure SQL Database. You'll then initiate a failover and observe the results, leveraging an application. \r\n", 27 | "\r\n", 28 | "\r\n", 29 | "**Set up** \r\n", 30 | "\r\n", 31 | "0. You should have opened this file using Azure Data Studio. If you didn't, please refer to Module 2 Activity 3 in the readme.md file to get set up. \r\n", 32 | "1. In the bar at the top of this screen, confirm or change the \"Kernel\" to **PowerShell**. This determines what language the code blocks in the file are. In this case, that language is PowerShell. \r\n", 33 | "2. Confirming the Kernel is **PowerShell**, for \"Attach to\", it should read **localhost**. \r\n", 34 | "\r\n", 35 | "Now that you're set up, you should read the text cells and \"Run\" the code cells by selecting the play button that appears in the left of a code cell when you hover over it. \r\n", 36 | "" 37 | ], 38 | "metadata": { 39 | "azdata_cell_guid": "5907a06a-b683-4e00-b847-8c033d93cbc7" 40 | } 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "source": [ 45 | "## Auto-failover groups in Azure SQL \r\n", 46 | "\r\n", 47 | "To configure auto-failover groups for a database(s) and observe the results in an application, you must complete the following steps: \r\n", 48 | "\r\n", 49 | "0. Confirm environment is properly configured\r\n", 50 | "1. Create an empty Azure SQL Database server in the failover region\r\n", 51 | "1. Create a failover group between the servers \r\n", 52 | "1. Add database(s) to the failover group \r\n", 53 | "1. Configure the network\r\n", 54 | "1. Configure your application(s)\r\n", 55 | "1. Run your application(s)\r\n", 56 | "1. Initiate a failover\r\n", 57 | "1. Fail back\r\n", 58 | "1. (Bonus) How many read replicas? \r\n", 59 | "\r\n", 60 | "This notebook will guide you through configuring auto-failover groups for your AdventureWorksID database. You'll then use a simple Java application to understand where reads and writes occur, and the importance of retry logic in your applications. Finally, you'll do a fun exercise to determine how many read-replicas are associated with a Business critical database that also has an auto-failover group. \r\n", 61 | "\r\n", 62 | ">Note: This activity is based off of a [tutorial in the documentation](https://docs.microsoft.com/en-us/azure/sql-database/sql-database-implement-geo-distributed-database?tabs=azure-powershell) that also has information about using the Azure portal and the Azure CLI. In this exercise, you will use the Az PowerShell module. " 63 | ], 64 | "metadata": { 65 | "azdata_cell_guid": "920f1f34-a236-43b9-8395-c3e947ec94a7" 66 | } 67 | }, 68 | { 69 | "cell_type": "markdown", 70 | "source": [ 71 | "**Step 0 - Confirm environment is properly configured**" 72 | ], 73 | "metadata": { 74 | "azdata_cell_guid": "2f0d4f1d-bc90-44f5-a1fb-d5d9d5639637" 75 | } 76 | }, 77 | { 78 | "cell_type": "markdown", 79 | "source": [ 80 | "Confirm the [Az PowerShell Module](https://docs.microsoft.com/en-us/powershell/azure/install-az-ps?view=azps-3.4.00) is installed with version 3.4.0+. " 81 | ], 82 | "metadata": { 83 | "azdata_cell_guid": "f42af32c-13e0-45f8-b97f-b456c8adb37f" 84 | } 85 | }, 86 | { 87 | "cell_type": "code", 88 | "source": [ 89 | "Get-InstalledModule -Name Az -AllVersions | select Name,Version" 90 | ], 91 | "metadata": { 92 | "azdata_cell_guid": "660a1161-06e0-442a-b308-6fb6d82a6785" 93 | }, 94 | "outputs": [ 95 | { 96 | "name": "stdout", 97 | "text": "\nName Version\n---- -------\nAz 3.5.0 \n\n\n", 98 | "output_type": "stream" 99 | } 100 | ], 101 | "execution_count": 1 102 | }, 103 | { 104 | "cell_type": "markdown", 105 | "source": [ 106 | "Confirm [Maven and Java](https://www.microsoft.com/en-us/sql-server/developer-get-started/java/windows) are installed and configured with Maven 3.6.3+ and Java 1.8.0_241+. " 107 | ], 108 | "metadata": { 109 | "azdata_cell_guid": "6d151b7a-df3c-4c5a-a276-63f3259e90f1" 110 | } 111 | }, 112 | { 113 | "cell_type": "code", 114 | "source": [ 115 | "mvn --version" 116 | ], 117 | "metadata": { 118 | "azdata_cell_guid": "7f7c6ebc-c84d-42af-9a9d-b7d61a9979c6" 119 | }, 120 | "outputs": [ 121 | { 122 | "name": "stdout", 123 | "text": "Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)\nMaven home: C:\\Users\\vmuser\\Downloads\\apache-maven-3.6.3-bin\\apache-maven-3.6.3\\bin\\..\nJava version: 1.8.0_241, vendor: Oracle Corporation, runtime: C:\\Program Files\\Java\\jdk1.8.0_241\\jre\nDefault locale: en_US, platform encoding: Cp1252\nOS name: \"windows 10\", version: \"10.0\", arch: \"amd64\", family: \"windows\"\n", 124 | "output_type": "stream" 125 | } 126 | ], 127 | "execution_count": 2 128 | }, 129 | { 130 | "cell_type": "markdown", 131 | "source": [ 132 | "If either of the above cells fail, please revisit the prerequisites before continuing. \r\n", 133 | "\r\n", 134 | "In the below cell, replace the `0406` with the ID you are using for the workshop. Also, add your subscription ID, your SQL authentication password, and the location of your main Azure SQL Database logical server. For `$drLocation`, you'll need to supply the region where you want your failover group to be. Ideally, you would select a paired region, which you can see the list of [here](https://docs.microsoft.com/en-us/azure/best-practices-availability-paired-regions). \r\n", 135 | "\r\n", 136 | "> Note: If you're taking this as part of an in-person workshop and were provided an environment to use, defer to instructor guidance on what region to use. " 137 | ], 138 | "metadata": { 139 | "azdata_cell_guid": "6abe1497-8822-481b-b0cf-35581ca21b4e" 140 | } 141 | }, 142 | { 143 | "cell_type": "code", 144 | "source": [ 145 | "# Add your info\r\n", 146 | "$unique_id = \"0406\"\r\n", 147 | "$subscriptionId = \"subscription\"\r\n", 148 | "$location = \"location\"\r\n", 149 | "$password = \"db password\"\r\n", 150 | "$drLocation = \"dr location\"\r\n", 151 | "\r\n", 152 | "# Do not modify\r\n", 153 | "$admin = \"cloudadmin\"\r\n", 154 | "$resourceGroup = \"azuresqlworkshop$($unique_id)\"\r\n", 155 | "$server = \"aw-server$($unique_id)\"\r\n", 156 | "$database = \"AdventureWorks$($unique_id)\"\r\n", 157 | "$drServer = \"aw-server$($unique_id)-dr\"\r\n", 158 | "$failoverGroup = \"aw-server-fg-$($unique_id)\"\r\n", 159 | "$firewallRule = \"VmFirewall\"\r\n", 160 | "$ip = Invoke-RestMethod -Uri 'https://ipinfo.io/ip'\r\n", 161 | "$ipAddress = $ip.Substring(0,$ip.Length-1) \r\n", 162 | "Write-Host \"Variables Received\"" 163 | ], 164 | "metadata": { 165 | "azdata_cell_guid": "6b2b94fd-470d-462e-bc9e-721a5b1f7b28" 166 | }, 167 | "outputs": [], 168 | "execution_count": null 169 | }, 170 | { 171 | "cell_type": "code", 172 | "source": [ 173 | "Set-AzContext -SubscriptionId $subscriptionId " 174 | ], 175 | "metadata": { 176 | "azdata_cell_guid": "241a155a-c6a1-4e8b-a20f-f9c83ae008dc" 177 | }, 178 | "outputs": [], 179 | "execution_count": null 180 | }, 181 | { 182 | "cell_type": "markdown", 183 | "source": [ 184 | "**Step 1 - Create an empty Azure SQL Database server in the failover region**" 185 | ], 186 | "metadata": { 187 | "azdata_cell_guid": "4db9aa26-4f07-44fe-8edf-e5d52efbace5" 188 | } 189 | }, 190 | { 191 | "cell_type": "code", 192 | "source": [ 193 | "# create a backup server in the failover region\r\n", 194 | "New-AzSqlServer -ResourceGroupName $resourceGroup `\r\n", 195 | " -ServerName $drServer `\r\n", 196 | " -Location $drLocation `\r\n", 197 | " -SqlAdministratorCredentials $(New-Object -TypeName System.Management.Automation.PSCredential `\r\n", 198 | " -ArgumentList $admin, $(ConvertTo-SecureString -String $password -AsPlainText -Force))\r\n", 199 | "Write-Host \"New Azure SQL Database logical server Created in different region\"" 200 | ], 201 | "metadata": { 202 | "azdata_cell_guid": "a7fb1b43-d614-4e32-b8fb-7694fb5a7d02" 203 | }, 204 | "outputs": [], 205 | "execution_count": null 206 | }, 207 | { 208 | "cell_type": "markdown", 209 | "source": [ 210 | "**Step 2 - Create a failover group between the servers**" 211 | ], 212 | "metadata": { 213 | "azdata_cell_guid": "4ffd546f-ab5b-4fa8-b0f3-8c0d23bc47cd" 214 | } 215 | }, 216 | { 217 | "cell_type": "code", 218 | "source": [ 219 | "# create a failover group between the servers\r\n", 220 | "New-AzSqlDatabaseFailoverGroup -ResourceGroupName $resourceGroup `\r\n", 221 | " -ServerName $server `\r\n", 222 | " -PartnerServerName $drServer `\r\n", 223 | " -FailoverGroupName $failoverGroup \r\n", 224 | "Write-Host \"New auto-failover group created between the two Azure SQL Database logical servers\"" 225 | ], 226 | "metadata": { 227 | "azdata_cell_guid": "1d93bfb6-e9c3-41df-bfb1-92fc0ec296ca", 228 | "tags": [] 229 | }, 230 | "outputs": [], 231 | "execution_count": null 232 | }, 233 | { 234 | "cell_type": "markdown", 235 | "source": [ 236 | "**Step 3 - Add database(s) to the failover group**" 237 | ], 238 | "metadata": { 239 | "azdata_cell_guid": "47eba5c0-64a3-432c-8b0c-0e029872b5c8" 240 | } 241 | }, 242 | { 243 | "cell_type": "code", 244 | "source": [ 245 | "# add the database to the failover group\r\n", 246 | "Get-AzSqlDatabase -ResourceGroupName $resourceGroup `\r\n", 247 | " -ServerName $server -DatabaseName $database | `\r\n", 248 | " Add-AzSqlDatabaseToFailoverGroup -ResourceGroupName $resourceGroup `\r\n", 249 | " -ServerName $server `\r\n", 250 | " -FailoverGroupName $failoverGroup\r\n", 251 | "Write-Host \"AdventureWorks database added to the auto-failover group\"" 252 | ], 253 | "metadata": { 254 | "azdata_cell_guid": "e00fe166-1896-45b4-aaa7-3e91c49cbdc8" 255 | }, 256 | "outputs": [], 257 | "execution_count": null 258 | }, 259 | { 260 | "cell_type": "markdown", 261 | "source": [ 262 | "The above step takes some time, because what you're doing is restoring the database in the other region, which involves copying the data from the original region to the DR region. You can work on **Step 5** and then come back here to check if it has completed. If it hasn't, you can work on **Step 6** and then check back here. " 263 | ], 264 | "metadata": { 265 | "azdata_cell_guid": "f6670a9e-b739-4df8-8f45-20351ad837d6" 266 | } 267 | }, 268 | { 269 | "cell_type": "markdown", 270 | "source": [ 271 | "**Step 4 - Configure the network**" 272 | ], 273 | "metadata": { 274 | "azdata_cell_guid": "2ea54109-e02e-4d5e-acad-e8a73331ac53" 275 | } 276 | }, 277 | { 278 | "cell_type": "code", 279 | "source": [ 280 | "# Add a firewall rules that gives your VM access to the new server\r\n", 281 | "New-AzSqlServerFirewallRule -ResourceGroupName $resourceGroup `\r\n", 282 | " -ServerName $drServer `\r\n", 283 | " -FirewallRuleName $firewallRule `\r\n", 284 | " -StartIpAddress $ipAddress `\r\n", 285 | " -EndIpAddress $ipAddress;" 286 | ], 287 | "metadata": { 288 | "azdata_cell_guid": "fc353f5d-d990-4591-82f8-b24338d404ad", 289 | "tags": [] 290 | }, 291 | "outputs": [], 292 | "execution_count": null 293 | }, 294 | { 295 | "cell_type": "markdown", 296 | "source": [ 297 | "What you've just done is deploy and configure and auto-failover group for you AdventureWorks database. Let's review. \r\n", 298 | "\r\n", 299 | "You started with a database and server in one location, with access from a virtual network (containing your VM) in that same location, this is what you did in Modules 2 and 3. In this notebook, you created a failover group from your original server to a new server in a different location, and added your AdventureWorks database to it. Finally, you added a firewall rule so that the new server/database in a different region can still be accessed from your VM. \r\n", 300 | "\r\n", 301 | "For the purposes of this activity (illustrating auto-failover groups) this is sufficient from a networking and VM perspective. However, this is slightly different from what you would do in an enterprise environment. In an enterprise environment, your \"VM\" will likely be a set of resources that make up some type of application. In the event of a failover of your database, you may want to failover your application/VMs/other resources to that new region as well. Both sets of resources will need access to the resources/servers/databases in the other region. In order to do this, you can use virtual network peering, virtual network to virtual network connections, or potentially something else (like ExpressRoute). It will depend on your scenario. You can learn more about what is needed to [design globally available services using Azure SQL Database here](https://docs.microsoft.com/en-us/azure/sql-database/sql-database-designing-cloud-solutions-for-disaster-recovery). " 302 | ], 303 | "metadata": { 304 | "azdata_cell_guid": "25035a1e-35e4-4c47-b175-7e116b6442e9" 305 | } 306 | }, 307 | { 308 | "cell_type": "markdown", 309 | "source": [ 310 | "**Step 5 - Configure your application(s)** \r\n", 311 | "\r\n", 312 | "For this activity, you'll leverage a sample Java application that attempts to write on your primary server and read what was just written from your secondary server. In order to use this app, you need to add your information to four lines of code. From the **Explorer** left-hand menu in Azure Data Studio, navigate to `azuresqlworkshop\\05-Availability\\fg\\app\\src\\main\\java\\com\\sqldbsamples\\App.java`. Clicking on the `App.java` file should open a text editor within Azure Data Studio. Update the lines near the top that require your specific information and then save the file. You only need to update the following lines (snippet from `App.java`): \r\n", 313 | "\r\n", 314 | "```java\r\n", 315 | " // UPDATE WITH YOUR INFO\r\n", 316 | " private static final String FAILOVER_GROUP_NAME = \"aw-server-fg-ID\"; // add workshop ID\r\n", 317 | " // UPDATE WITH YOUR INFO\r\n", 318 | " private static final String DB_NAME = \"AdventureWorksID\"; // add workshop ID\r\n", 319 | " // UPDATE WITH YOUR INFO\r\n", 320 | " private static final String USER = \"cloudadmin\"; // add database user\r\n", 321 | " // UPDATE WITH YOUR INFO\r\n", 322 | " private static final String PASSWORD = \"\"; // add database password\r\n", 323 | "``` \r\n", 324 | "\r\n", 325 | "Review this file and determine what the two queries that are running do. \r\n", 326 | "\r\n", 327 | "Be sure to save the file before you close it. " 328 | ], 329 | "metadata": { 330 | "azdata_cell_guid": "5e030572-4630-49d7-ab00-0087904048a7" 331 | } 332 | }, 333 | { 334 | "cell_type": "markdown", 335 | "source": [ 336 | "**Step 6 - Run your application(s)**\r\n", 337 | "\r\n", 338 | "This app runs from the command-line. Open Command prompt (you can type `cmd` in the Windows search bar and select **Enter**). \r\n", 339 | "\r\n", 340 | "If you've followed the prerequisites, you just need to update `` to the VM username you use to log in to this VM. Update and then run the following commands in Command prompt. \r\n", 341 | "\r\n", 342 | "```cmd\r\n", 343 | "cd C:\\Users\\vmuser\\sqlworkshops-azuresqlworkshop\\azuresqlworkshop\\05-Availability\\fg\\app\r\n", 344 | "mvn package\r\n", 345 | "mvn -q -e exec:java \"-Dexec.mainClass=com.sqldbsamples.App\"\r\n", 346 | "```\r\n", 347 | "\r\n", 348 | "The first 5-10 inserts may fail. As long as it settles to both being successful, your app is running properly. \r\n", 349 | "\r\n", 350 | "For the next steps, it is recommended to split your screen so you can see both Azure Data Studio and that command prompt window. Example below: \r\n", 351 | "\r\n", 352 | "![](./graphics/splitscreen.png)\r\n", 353 | "" 354 | ], 355 | "metadata": { 356 | "azdata_cell_guid": "44014cff-63b7-4ba6-ab41-aec3c44598f1" 357 | } 358 | }, 359 | { 360 | "cell_type": "markdown", 361 | "source": [ 362 | "**Step 7 - Initiate a failover** \r\n", 363 | "\r\n", 364 | "\r\n", 365 | "Check the status of the secondary server." 366 | ], 367 | "metadata": { 368 | "azdata_cell_guid": "91dd82dd-5b93-4be5-96d4-80a914e90e8a" 369 | } 370 | }, 371 | { 372 | "cell_type": "code", 373 | "source": [ 374 | "(Get-AzSqlDatabaseFailoverGroup -FailoverGroupName $failoverGroup `\r\n", 375 | " -ResourceGroupName $resourceGroup -ServerName $drServer).ReplicationRole" 376 | ], 377 | "metadata": { 378 | "azdata_cell_guid": "db25999b-ba4e-4c8a-a2c5-27dc79534fd2" 379 | }, 380 | "outputs": [ 381 | { 382 | "name": "stdout", 383 | "text": "Secondary\n", 384 | "output_type": "stream" 385 | } 386 | ], 387 | "execution_count": 9 388 | }, 389 | { 390 | "cell_type": "markdown", 391 | "source": [ 392 | "The result of the previous cell tells you if the secondary server in the auto-failover group is being used as the primary or secondary database." 393 | ], 394 | "metadata": { 395 | "azdata_cell_guid": "642e84cb-3fb8-4e44-92df-aee73a74c4ac" 396 | } 397 | }, 398 | { 399 | "cell_type": "markdown", 400 | "source": [ 401 | "We can now see what happens when a failover occurs by starting a manual failover with the Azure PowerShell commands below. \r\n", 402 | "\r\n", 403 | "When the failover occurs, you'll notice that some of the inserts and reads may fail briefly. But since our app keeps retrying, the application doesn't fail. And once the failover has completed, the inserts and reads become successful again. " 404 | ], 405 | "metadata": { 406 | "azdata_cell_guid": "74adcbb5-06e5-41c9-bb5a-ea4f5ab1ca59" 407 | } 408 | }, 409 | { 410 | "cell_type": "code", 411 | "source": [ 412 | "Switch-AzSqlDatabaseFailoverGroup -ResourceGroupName $resourceGroup `\r\n", 413 | " -ServerName $drServer -FailoverGroupName $failoverGroup" 414 | ], 415 | "metadata": { 416 | "azdata_cell_guid": "02880372-715f-4bf1-b65f-6926635a1360" 417 | }, 418 | "outputs": [ 419 | { 420 | "name": "stdout", 421 | "text": "", 422 | "output_type": "stream" 423 | } 424 | ], 425 | "execution_count": 10 426 | }, 427 | { 428 | "cell_type": "markdown", 429 | "source": [ 430 | "Check the status of the secondary server." 431 | ], 432 | "metadata": { 433 | "azdata_cell_guid": "1c5ff262-8a51-4e3f-b266-0c08f7b50c34" 434 | } 435 | }, 436 | { 437 | "cell_type": "code", 438 | "source": [ 439 | "(Get-AzSqlDatabaseFailoverGroup -FailoverGroupName $failoverGroup `\r\n", 440 | " -ResourceGroupName $resourceGroup -ServerName $drServer).ReplicationRole" 441 | ], 442 | "metadata": { 443 | "azdata_cell_guid": "4410b85a-1054-44c5-930b-fce89b2ae9cf" 444 | }, 445 | "outputs": [ 446 | { 447 | "name": "stdout", 448 | "text": "Primary\n", 449 | "output_type": "stream" 450 | } 451 | ], 452 | "execution_count": 11 453 | }, 454 | { 455 | "cell_type": "markdown", 456 | "source": [ 457 | "**Step 8 - Fail back** \r\n", 458 | "\r\n", 459 | "Now we can fail back to our original configuration by using a similar command. " 460 | ], 461 | "metadata": { 462 | "azdata_cell_guid": "aabb9efe-cdd9-4589-ba1f-3cdb950588fc" 463 | } 464 | }, 465 | { 466 | "cell_type": "code", 467 | "source": [ 468 | "Switch-AzSqlDatabaseFailoverGroup -ResourceGroupName $resourceGroup `\r\n", 469 | " -ServerName $server -FailoverGroupName $failoverGroup" 470 | ], 471 | "metadata": { 472 | "azdata_cell_guid": "62fc5399-1607-43fd-9819-4d8976816e2f" 473 | }, 474 | "outputs": [ 475 | { 476 | "name": "stdout", 477 | "text": "", 478 | "output_type": "stream" 479 | } 480 | ], 481 | "execution_count": 12 482 | }, 483 | { 484 | "cell_type": "markdown", 485 | "source": [ 486 | "Check the status of the secondary server." 487 | ], 488 | "metadata": { 489 | "azdata_cell_guid": "ee499c44-f704-41d2-a702-116bf29d8c33" 490 | } 491 | }, 492 | { 493 | "cell_type": "code", 494 | "source": [ 495 | "(Get-AzSqlDatabaseFailoverGroup -FailoverGroupName $failoverGroup `\r\n", 496 | " -ResourceGroupName $resourceGroup -ServerName $drServer).ReplicationRole" 497 | ], 498 | "metadata": { 499 | "azdata_cell_guid": "63ac9580-f394-4e8f-9fe5-9e1c23270482" 500 | }, 501 | "outputs": [ 502 | { 503 | "name": "stdout", 504 | "text": "Secondary\n", 505 | "output_type": "stream" 506 | } 507 | ], 508 | "execution_count": 13 509 | }, 510 | { 511 | "cell_type": "markdown", 512 | "source": [ 513 | "**(Bonus) Step 9 - How many read replicas?**" 514 | ], 515 | "metadata": { 516 | "azdata_cell_guid": "a6008751-671f-4a08-9700-3e99b3f4fae0" 517 | } 518 | }, 519 | { 520 | "cell_type": "markdown", 521 | "source": [ 522 | "You've seen how you can use the primary/secondary in an auto-failover group to help offload read-heavy workloads from the primary. In the previous activity, you also saw how in certain service tiers, like Business critical, you get a read-replica without setting up auto-failover groups. This begs the question, how many read-replicas do you have with a Business critical Azure SQL Database with an auto-failover group? \r\n", 523 | "\r\n", 524 | "Maybe you guessed it, but the answer is **3**. You can investigate this claim by using SSMS (or ADS) to connect to the following servers (be sure to specify the database under connection properties) and running the query to check if it's ReadWrite or ReadOnly below. \r\n", 525 | "\r\n", 526 | "The easiest way to do this is to create a New Database Engine Query by selecting **File** > **New** > **Database Engine Query**. \r\n", 527 | "\r\n", 528 | "![](./graphics/newdbenginequery.png)\r\n", 529 | "\r\n", 530 | "Connections: \r\n", 531 | "* `aw-server-fg-`YourID`.database.windows.net` \r\n", 532 | "* `aw-server-fg-`YourID`.database.windows.net` with Additional Connection Parameter `ApplicationIntent=ReadOnly` \r\n", 533 | "* `aw-server-fg-`YourID`.secondary.database.windows.net` \r\n", 534 | "* `aw-server-fg-`YourID`.secondary.database.windows.net` with Additional Connection Parameter `ApplicationIntent=ReadOnly` \r\n", 535 | "\r\n", 536 | "Command to run in each: \r\n", 537 | "```sql \r\n", 538 | "SELECT DATABASEPROPERTYEX(DB_NAME(), 'Updateability')\r\n", 539 | "``` " 540 | ], 541 | "metadata": { 542 | "azdata_cell_guid": "2204a9a4-767f-41dd-9e98-75a265eb34f9" 543 | } 544 | } 545 | ] 546 | } -------------------------------------------------------------------------------- /05-Availability/fg/graphics/newdbenginequery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MicrosoftDocs/mslearn-azure-sql-fundamentals/ad17351bf330631dd22b99642c1064dd073e763b/05-Availability/fg/graphics/newdbenginequery.png -------------------------------------------------------------------------------- /05-Availability/fg/graphics/splitscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MicrosoftDocs/mslearn-azure-sql-fundamentals/ad17351bf330631dd22b99642c1064dd073e763b/05-Availability/fg/graphics/splitscreen.png -------------------------------------------------------------------------------- /05-Availability/ostress.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MicrosoftDocs/mslearn-azure-sql-fundamentals/ad17351bf330631dd22b99642c1064dd073e763b/05-Availability/ostress.exe -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | --- 2 | page_type: sample 3 | languages: 4 | - csharp 5 | products: 6 | - dotnet 7 | description: "Add 150 character max description" 8 | urlFragment: "update-this-to-unique-url-stub" 9 | --- 10 | 11 | # Official Microsoft Sample 12 | 13 | 20 | 21 | Give a short description for your sample here. What does it do and why is it important? 22 | 23 | ## Contents 24 | 25 | Outline the file contents of the repository. It helps users navigate the codebase, build configuration and any related assets. 26 | 27 | | File/folder | Description | 28 | |-------------------|--------------------------------------------| 29 | | `src` | Sample source code. | 30 | | `.gitignore` | Define what to ignore at commit time. | 31 | | `CHANGELOG.md` | List of changes to the sample. | 32 | | `CONTRIBUTING.md` | Guidelines for contributing to the sample. | 33 | | `README.md` | This README file. | 34 | | `LICENSE` | The license for the sample. | 35 | 36 | ## Prerequisites 37 | 38 | Outline the required components and tools that a user might need to have on their machine in order to run the sample. This can be anything from frameworks, SDKs, OS versions or IDE releases. 39 | 40 | ## Setup 41 | 42 | Explain how to prepare the sample once the user clones or downloads the repository. The section should outline every step necessary to install dependencies and set up any settings (for example, API keys and output folders). 43 | 44 | ## Running the sample 45 | 46 | Outline step-by-step instructions to execute the sample and see its output. Include steps for executing the sample from the IDE, starting specific services in the Azure portal or anything related to the overall launch of the code. 47 | 48 | ## Key concepts 49 | 50 | Provide users with more context on the tools and services used in the sample. Explain some of the code that is being used and how services interact with each other. 51 | 52 | ## Contributing 53 | 54 | This project welcomes contributions and suggestions. Most contributions require you to agree to a 55 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us 56 | the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. 57 | 58 | When you submit a pull request, a CLA bot will automatically determine whether you need to provide 59 | a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions 60 | provided by the bot. You will only need to do this once across all repos using our CLA. 61 | 62 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 63 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or 64 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 65 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). 40 | 41 | --------------------------------------------------------------------------------