{"id":502,"date":"2012-01-17T12:01:00","date_gmt":"2012-01-17T12:01:00","guid":{"rendered":"\/blogs\/bobb\/post\/SQL-Server-2012-FileTable-and-T-SQL-on-AlwaysOn-secondary-replicas.aspx"},"modified":"2014-01-20T12:21:35","modified_gmt":"2014-01-20T20:21:35","slug":"sql-server-2012-filetable-and-t-sql-on-alwayson-secondary-replicas","status":"publish","type":"post","link":"https:\/\/www.sqlskills.com\/blogs\/bobb\/sql-server-2012-filetable-and-t-sql-on-alwayson-secondary-replicas\/","title":{"rendered":"SQL Server 2012 FileTable and T-SQL on AlwaysOn secondary replicas"},"content":{"rendered":"<p>\nOK, back to PathName() with AlwaysOn, which I started on in the<a href=\"http:\/\/3.209.169.194\/blogs\/bobb\/sql-server-2012-filetables-alwayson-support-and-pathname\/\" class=\"broken_link\"> previous blog post<\/a>. PathName() in SQL Server 2012 doesn&#39;t return the computer name by default (&quot;AlwaysOn1&quot; or &quot;AlwaysOn2&quot; in my example) but returns the VNN name (virtual network name). That is, it returns the availability group &quot;listener share&quot; name. In my case, the PathName() would start with <a href=\"file:\/\/\\\\AlwaysOnAG1\">\\\\AlwaysOnAG1<\/a>. There&#39;s an additional option in SQL Server 2012 PathName(), that allows you to return the current replica name. So, when &quot;AlwaysOn1&quot; is the current primary replica, it returns that; when we fail over to &quot;AlwaysOn2&quot;, that&#39;s what name is returned. In addition, GetFileNamespacePath() and FileTableRootPath() always return the availability group listener name, they don&#39;t have an option to return the current replica name.\n<\/p>\n<p>\nFinally, I&#39;ll discuss using AlwaysOn, FilePath(), T-SQL access and secondary replicas.In theory, ADO.NET 4.02 (and, of course, SQLNativeClient 11ODBC\/OLE DB and Microsoft JDBC 4.0 driver) allows you to declare your ApplicationIntent as ReadOnly or ReadWrite. ReadWrite is the default. Adding either ApplicationIntent=ReadOnly or ApplicationIntent=ReadWrite in the SSMS Connection dialog is accepted, but either one allows connection to the secondary replica. This is because, by default, secondary replicas are configured with &quot;Readable Secondary=Yes&quot; rather than &quot;Readable Secondary=Read-intent&quot;. Configuring a secondary as &quot;Readable secondary=Read-Intent&quot; disallows connections that do not specify ApplicationIntent=ReadOnly in the connection string. Obviously, connecting as &quot;ReadWrite&quot; to a ReadOnly replica errors out if you try and do something other than read. Check out <a href=\"https:\/\/login.live.com\/login.srf?wa=wsignin1.0&amp;rpsnv=11&amp;ct=1357286092&amp;rver=6.0.5286.0&amp;wp=MBI&amp;wreply=http:%2F%2Fblogs.msdn.com%2Fb%2Fsqlserverstorageengine%2Farchive%2F2011%2F12%2F22%2Falwayson-why-there-are-two-options-to-enable-a-secondary-replica-for-%2F&amp;lc=1033&amp;id=271611\">Sunil&#39;s excellent blog post<\/a> on the motivations for these secondary replica settings.\n<\/p>\n<p>\nNow that we&#39;re connected (in T-SQL) to the secondary replica, let&#39;s try and get the PathName() from here:\n<\/p>\n<p>\nSELECT Name, file_stream.PathName() FROM NWTab;\n<\/p>\n<p>\nMsg 33447, Level 16, State 1, Line 1<br \/>\nCannot access file_stream column in FileTable &#39;NWTab&#39;, because FileTable doesn&#39;t support row versioning. Either set transaction level to something other than READ COMMITTED SNAPSHOT or SNAPSHOT, or use READCOMMITTEDLOCK table hint.\n<\/p>\n<p>\nNow, this was surprising&#8230;I checked the snapshot info in sys.databases and also DBCC USEROPTIONS. Neither snapshot isolation level was turned on or being used. And setting the iso level to, say, repeatable read or even the dreaded read uncommitted didn&#39;t help. But using the READCOMMITTEDLOCK did. Hmmm&#8230;\n<\/p>\n<p>\nBut of course, Sunil had <a href=\"http:\/\/blogs.msdn.com\/b\/sqlserverstorageengine\/archive\/2011\/12\/22\/alwayson-minimizing-blocking-of-redo-thread-when-running-reporting-workload-on-secondary-replica.aspx\" class=\"broken_link\">the answer for this one too<\/a>&#8230;&quot;To avoid this blocking completely, all transaction isolation levels used in an application on the secondary replica are mapped transparently to Snapshot Isolation&#8230;&quot; And this behavior is more obliquely <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/gg492086(v=SQL.110).aspx\">documented in the BOL, here<\/a>. But&nbsp;Sunil&#39;s blog post&nbsp;does go on to say &quot;You may ask how about locking hints? Well, all locking hints are ignored.&quot; But the READCOMMITTEDLOCK locking hint does work in this case (modulo the effects it might have on performance, as Sunil mentions). So at this point I wonder if the READCOMMITTEDLOCK locking hint on a FileTable has a special dispensation (other locking hints, do, in fact, fail to have the desired effect), but I&#39;ll need to revisit this in 2012 RTM. BTW, it&#39;s only using the file_stream column of the FileTable that causes this, other columns work fine. But PathName() and GetFileNamespacePath() are methods on the column, so you can&#39;t use these, or access the column in T-SQL, on readonly secondaries without the hint.\n<\/p>\n<p>\nBack to BOL comment, changing the NON_TRANSACTED_ACCESS to READ_ONLY (on the primary replica) changes the behavior on the secondary as promised, but now I can&#39;t write to the FileTable using the file system. As expected.\n<\/p>\n<p>\nTwo more things to mention. Firstly, Msg 33447 isn&#39;t a mistaken error message. You can, of course, attempt to access the file_stream column in a FileTable from the *primary* replica using Snapshot isolation. Then you&#39;ll receive the error, and changing the iso level&nbsp;WILL help. When enabling read-committed snapshot or snapshot you DO get this useful (but slightly misleading, IMHO) message on the ALTER DATABASE DDL statement: &quot;When the FILESTREAM database option NON_TRANSACTED_ACCESS is set to FULL and the READ_COMMITTED_SNAPSHOT or the ALLOW_SNAPSHOT_ISOLATION options are on, T-SQL and transactional read access to FILESTREAM data in the context of a FILETABLE is blocked.&quot;. That&#39;s not quite true; if the options are on and you *USE* snapshot iso levels, you&#39;ll get the error. Changing the iso level to a non-snapshot iso level or using the READCOMMITTEDLOCK hint WILL succeed on the primary.\n<\/p>\n<p>\nFinally, remember that &quot;ordinary&quot; (i.e. non-FileTable) tables containing filestream columns DO support snapshot isolation levels as of SQL Server 2008 R2. It should be only the FileTable, with its non-transacted access, that has this behavior with snapshot isolation on the primary and readonly secondaries. And, in fact, this does test out to be the case, an &quot;ordinary&quot; filestream column works fine, even in the same database.\n<\/p>\n<p>\nEnough? \ud83d\ude09 I even turned moderated blog comments back on (against my better judgement, the amount of spam comments is amazing), if this is a useful discussion vehicle. Or, you know where to find me&#8230; Cheers.\n<\/p>\n<p>\nNB: Since writing this post, I discovered this post on Availability Group and Filetable &#8211; <a href=\"http:\/\/dangerousdba.blogspot.com\/2012\/07\/filetable-with-alwayson-ags-bug.html\">http:\/\/dangerousdba.blogspot.com\/2012\/07\/filetable-with-alwayson-ags-bug.html<\/a>. Thanks Rick!\n<\/p>\n<p>\n@bobbeauch<\/p>\n","protected":false},"excerpt":{"rendered":"<p>OK, back to PathName() with AlwaysOn, which I started on in the previous blog post. PathName() in SQL Server 2012 doesn&#39;t return the computer name by default (&quot;AlwaysOn1&quot; or &quot;AlwaysOn2&quot; in my example) but returns the VNN name (virtual network name). That is, it returns the availability group &quot;listener share&quot; name. In my case, the [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[16,17,31],"tags":[],"class_list":["post-502","post","type-post","status-publish","format-standard","hentry","category-filestream-storage","category-filetable","category-sql-server-2012"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v21.9.1 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>SQL Server 2012 FileTable and T-SQL on AlwaysOn secondary replicas - Bob Beauchemin<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.sqlskills.com\/blogs\/bobb\/sql-server-2012-filetable-and-t-sql-on-alwayson-secondary-replicas\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"SQL Server 2012 FileTable and T-SQL on AlwaysOn secondary replicas - Bob Beauchemin\" \/>\n<meta property=\"og:description\" content=\"OK, back to PathName() with AlwaysOn, which I started on in the previous blog post. PathName() in SQL Server 2012 doesn&#039;t return the computer name by default (&quot;AlwaysOn1&quot; or &quot;AlwaysOn2&quot; in my example) but returns the VNN name (virtual network name). That is, it returns the availability group &quot;listener share&quot; name. In my case, the [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.sqlskills.com\/blogs\/bobb\/sql-server-2012-filetable-and-t-sql-on-alwayson-secondary-replicas\/\" \/>\n<meta property=\"og:site_name\" content=\"Bob Beauchemin\" \/>\n<meta property=\"article:published_time\" content=\"2012-01-17T12:01:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2014-01-20T20:21:35+00:00\" \/>\n<meta name=\"author\" content=\"Bob Beauchemin\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Bob Beauchemin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/sql-server-2012-filetable-and-t-sql-on-alwayson-secondary-replicas\/\",\"url\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/sql-server-2012-filetable-and-t-sql-on-alwayson-secondary-replicas\/\",\"name\":\"SQL Server 2012 FileTable and T-SQL on AlwaysOn secondary replicas - Bob Beauchemin\",\"isPartOf\":{\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/#website\"},\"datePublished\":\"2012-01-17T12:01:00+00:00\",\"dateModified\":\"2014-01-20T20:21:35+00:00\",\"author\":{\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/#\/schema\/person\/62bfa986c5b5d28fcffd8b4fc409c73e\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/sql-server-2012-filetable-and-t-sql-on-alwayson-secondary-replicas\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.sqlskills.com\/blogs\/bobb\/sql-server-2012-filetable-and-t-sql-on-alwayson-secondary-replicas\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/sql-server-2012-filetable-and-t-sql-on-alwayson-secondary-replicas\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Filestream Storage\",\"item\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/category\/filestream-storage\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"SQL Server 2012 FileTable and T-SQL on AlwaysOn secondary replicas\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/#website\",\"url\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/\",\"name\":\"Bob Beauchemin\",\"description\":\"SQL Server Blog\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/#\/schema\/person\/62bfa986c5b5d28fcffd8b4fc409c73e\",\"name\":\"Bob Beauchemin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/6f80e6cc667410857fa6a21931dc528b8092f4d112bf7a8ff7c267674d44ee37?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/6f80e6cc667410857fa6a21931dc528b8092f4d112bf7a8ff7c267674d44ee37?s=96&d=mm&r=g\",\"caption\":\"Bob Beauchemin\"},\"sameAs\":[\"http:\/www.sqlskills.com\/blogs\/bobb\/\"],\"url\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/author\/bobb\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"SQL Server 2012 FileTable and T-SQL on AlwaysOn secondary replicas - Bob Beauchemin","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.sqlskills.com\/blogs\/bobb\/sql-server-2012-filetable-and-t-sql-on-alwayson-secondary-replicas\/","og_locale":"en_US","og_type":"article","og_title":"SQL Server 2012 FileTable and T-SQL on AlwaysOn secondary replicas - Bob Beauchemin","og_description":"OK, back to PathName() with AlwaysOn, which I started on in the previous blog post. PathName() in SQL Server 2012 doesn&#39;t return the computer name by default (&quot;AlwaysOn1&quot; or &quot;AlwaysOn2&quot; in my example) but returns the VNN name (virtual network name). That is, it returns the availability group &quot;listener share&quot; name. In my case, the [&hellip;]","og_url":"https:\/\/www.sqlskills.com\/blogs\/bobb\/sql-server-2012-filetable-and-t-sql-on-alwayson-secondary-replicas\/","og_site_name":"Bob Beauchemin","article_published_time":"2012-01-17T12:01:00+00:00","article_modified_time":"2014-01-20T20:21:35+00:00","author":"Bob Beauchemin","twitter_misc":{"Written by":"Bob Beauchemin","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/sql-server-2012-filetable-and-t-sql-on-alwayson-secondary-replicas\/","url":"https:\/\/www.sqlskills.com\/blogs\/bobb\/sql-server-2012-filetable-and-t-sql-on-alwayson-secondary-replicas\/","name":"SQL Server 2012 FileTable and T-SQL on AlwaysOn secondary replicas - Bob Beauchemin","isPartOf":{"@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/#website"},"datePublished":"2012-01-17T12:01:00+00:00","dateModified":"2014-01-20T20:21:35+00:00","author":{"@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/#\/schema\/person\/62bfa986c5b5d28fcffd8b4fc409c73e"},"breadcrumb":{"@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/sql-server-2012-filetable-and-t-sql-on-alwayson-secondary-replicas\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.sqlskills.com\/blogs\/bobb\/sql-server-2012-filetable-and-t-sql-on-alwayson-secondary-replicas\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/sql-server-2012-filetable-and-t-sql-on-alwayson-secondary-replicas\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.sqlskills.com\/blogs\/bobb\/"},{"@type":"ListItem","position":2,"name":"Filestream Storage","item":"https:\/\/www.sqlskills.com\/blogs\/bobb\/category\/filestream-storage\/"},{"@type":"ListItem","position":3,"name":"SQL Server 2012 FileTable and T-SQL on AlwaysOn secondary replicas"}]},{"@type":"WebSite","@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/#website","url":"https:\/\/www.sqlskills.com\/blogs\/bobb\/","name":"Bob Beauchemin","description":"SQL Server Blog","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.sqlskills.com\/blogs\/bobb\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/#\/schema\/person\/62bfa986c5b5d28fcffd8b4fc409c73e","name":"Bob Beauchemin","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/6f80e6cc667410857fa6a21931dc528b8092f4d112bf7a8ff7c267674d44ee37?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/6f80e6cc667410857fa6a21931dc528b8092f4d112bf7a8ff7c267674d44ee37?s=96&d=mm&r=g","caption":"Bob Beauchemin"},"sameAs":["http:\/www.sqlskills.com\/blogs\/bobb\/"],"url":"https:\/\/www.sqlskills.com\/blogs\/bobb\/author\/bobb\/"}]}},"_links":{"self":[{"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/posts\/502","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/comments?post=502"}],"version-history":[{"count":0,"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/posts\/502\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/media?parent=502"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/categories?post=502"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/tags?post=502"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}