Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
И снова про автономные транзакции с помощью CLR
|
|||
|---|---|---|---|
|
#18+
Добрый день! Возникла потребность логгирования процесса обработки данных на SQL Server 2005 в автономной транзакции. Интернет предлагает 3 стандартных обходных маневра - с loopback linked server'ом, табличной переменной и написанием хранимой процедуры на CLR. Т.к. первые 2 варианта мне по тем или иным причинам не нравятся (покупной продукт, клиентское приложение - "черный ящик", требования к производительности и надежности), попробовал сделать хранимую процедуру на CLR. Забегая вперед, скажу, что несмотря на все рецепты и уверения Микрософт на МСДН, автономное соединение из CLR подхватывает "внешнюю" транзакцию! Создаем таблицу CREATE TABLE [dbo].[EventLog]( [ID] uniqueidentifier default NEWID() not null primary key, [EventBody] varchar(max) ) ON [PRIMARY] GO Создаем хранимую процедуру CLR public static class Logger { private const string cmdWriteLog = "INSERT INTO [dbo].[EventLog] ([EventBody]) VALUES (@EventBody)"; private const string unspecified = "<UNSPECIFIED>"; [SqlFunction] public static void LogWrite(string pEventBody) { try { using (var transaction = new TransactionScope(TransactionScopeOption.RequiresNew)) { using (var connection = new SqlConnection("context connection=true")) { connection.Open(); using (var command = connection.CreateCommand()) { command.CommandText = cmdWriteLog; command.Parameters.Add("@EventBody", System.Data.SqlDbType.Text); if (pEventBody == null || string.IsNullOrEmpty(pEventBody)) command.Parameters["@EventBody"].Value = string.Empty; else command.Parameters["@EventBody"].Value = pEventBody; command.ExecuteNonQuery(); transaction.Complete(); } } // Connection } // Transaction scope } catch (Exception) { } } } Прописываем нашу сборку на сервере sp_configure 'clr enabled', 1 RECONFIGURE IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[LogWriteInternal]') AND type in (N'P', N'PC')) DROP PROCEDURE [dbo].[LogWriteInternal] IF EXISTS (SELECT * FROM sys.assemblies asms WHERE asms.name = N'SqlServerFunctions' and is_user_defined = 1) DROP ASSEMBLY [SqlServerFunctions] CREATE ASSEMBLY SqlServerFunctions FROM 'c:\Test\SqlServerFunctions.dll' WITH PERMISSION_SET = SAFE CREATE PROCEDURE [dbo].[LogWriteInternal] ( @pEventBody nvarchar(max) ) AS EXTERNAL NAME SqlServerFunctions.Logger.LogWrite И, наконец, тестируемся. Если вызываем процедуру без явного объявления транзакции, сообщение пишется в лог. Если делаем явное объявление/откат транзакции, сообщение не пишется! BEGIN TRAN DECLARE @pEventBody nvarchar(max) SET @pEventBody = 'This is an event body' EXEC [dbo].[LogWriteInternal] @pEventBody ROLLBACK TRAN Вопрос: то ли Микрософт обманывает, и функция CLR получает соединение, из которого происходит вызов (вместо открытия нового соединения), то ли TransactionScopeOption.RequiresNew не создает автономную транзакцию, а подключает меня к "уже имеющейся". Кто-нибудь сумел победить это, и сумел сделать автономную транзакцию с помощью CLR? Поможите, люди добрые! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.02.2015, 16:45 |
|
||
|
И снова про автономные транзакции с помощью CLR
|
|||
|---|---|---|---|
|
#18+
Stibrus, да вроде все логично авторIf you need to connect to the same server on which the stored procedure or function is running, use the context connection in most cases. This has benefits such as Код: sql 1. and not having to reauthenticate. вот тут костыль через CLR описан , идея в том что они Context Connection используют только для получения инфы о сервере, а затем устанавливают Regular Connection на основе полученной инфы. И устанавливают Enlist = false, чтобы не участвовать в ambient транзакции. Но оно вам надо? может лучше через linked server? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.02.2015, 17:33 |
|
||
|
И снова про автономные транзакции с помощью CLR
|
|||
|---|---|---|---|
|
#18+
churupaha, в статье поиском найти "Simulating Autonomous Transactions"... а то статья о другом трохи. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.02.2015, 17:38 |
|
||
|
И снова про автономные транзакции с помощью CLR
|
|||
|---|---|---|---|
|
#18+
churupaha вот тут костыль через CLR описан , идея в том что они Context Connection используют только для получения инфы о сервере, а затем устанавливают Regular Connection на основе полученной инфы. И устанавливают Enlist = false, чтобы не участвовать в ambient транзакции. Но оно вам надо? может лучше через linked server? Благодарю! Не могу найти ссылку на МСДНе, которая сбила меня с толку, но это случилось :) Я подумаю над Вашим советом с linked server, т.к. описанный по Вашей ссылке метод, кажется, подразумевает много неприятностей (ALTER DATABASE .... SET TRUSTWORTHY ON, установку сборки в режиме UNSAFE). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.02.2015, 20:50 |
|
||
|
И снова про автономные транзакции с помощью CLR
|
|||
|---|---|---|---|
|
#18+
event notification для userconfigurable_* + sp_trace_generateevent 15757563 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.02.2015, 21:31 |
|
||
|
И снова про автономные транзакции с помощью CLR
|
|||
|---|---|---|---|
|
#18+
Stibrus(ALTER DATABASE .... SET TRUSTWORTHY ON, установку сборки в режиме UNSAFE). Я ни в коем случае вас не агитирую в конкретно этом случае использовать CLR, наоборот. Просто прокомментирую выделенное по поводу развертывания UNSAFE сборки. Правильно так: 1) подписуете сборку ключем 2) на стороне sql server Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.02.2015, 21:57 |
|
||
|
И снова про автономные транзакции с помощью CLR
|
|||
|---|---|---|---|
|
#18+
+ Код: sql 1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.02.2015, 21:59 |
|
||
|
И снова про автономные транзакции с помощью CLR
|
|||
|---|---|---|---|
|
#18+
invmevent notification для userconfigurable_* + sp_trace_generateevent 15757563 invmevent notification для userconfigurable_* + sp_trace_generateevent 15757563 Благодарю, но в моем случае загвоздка в том, что управляющее приложение - коробочный продукт, я не могу "протолкнуть информацию наверх", чтобы там ее обработать. churupahaЯ ни в коем случае вас не агитирую в конкретно этом случае использовать CLR, наоборот. Еще раз спасибо, всё заработало "на 5 баллов". Насчет выбора между loopback и CLR - поставлю вопрос перед DBA на работе, посмотрим, что ответят. Есть один момент, который вызывает у меня сомнение: как себя поведет linked server loopback в распределенной транзакции, если, например, будет вовлечен Оракл? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.03.2015, 00:37 |
|
||
|
И снова про автономные транзакции с помощью CLR
|
|||
|---|---|---|---|
|
#18+
Забыл сказать: у меня всё заработало с UNSAFE, хотя кое-где почему-то пишут, что понадобится EXTERNAL_ACCESS ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.03.2015, 00:39 |
|
||
|
И снова про автономные транзакции с помощью CLR
|
|||
|---|---|---|---|
|
#18+
StibrusЕсть один момент, который вызывает у меня сомнение: как себя поведет linked server loopback в распределенной транзакции, если, например, будет вовлечен Оракл? remote proc transaction promotion msdnIf this option is set to FALSE (or OFF), a local transaction will not be promoted to a distributed transaction while calling a remote procedure call on a linked server. StibrusЗабыл сказать: у меня всё заработало с UNSAFE, хотя кое-где почему-то пишут, что понадобится EXTERNAL_ACCESS Заработает и это. Просто сделаете: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.03.2015, 09:53 |
|
||
|
И снова про автономные транзакции с помощью CLR
|
|||
|---|---|---|---|
|
#18+
Stibrusя не могу "протолкнуть информацию наверх", чтобы там ее обработать.Не нужно ничего "проталкивать". Все работает на уровне сиквела. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.03.2015, 10:19 |
|
||
|
И снова про автономные транзакции с помощью CLR
|
|||
|---|---|---|---|
|
#18+
invmStibrusя не могу "протолкнуть информацию наверх", чтобы там ее обработать.Не нужно ничего "проталкивать". Все работает на уровне сиквела.Если речь про Service Broker, то надо обдумать. Как-то не смотрел в его сторону. З.Ы. Когда заводил вопрос, не нашел поиском тему по вашей ссылке, наверное, из-за названия. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.03.2015, 10:41 |
|
||
|
И снова про автономные транзакции с помощью CLR
|
|||
|---|---|---|---|
|
#18+
invmevent notification для userconfigurable_* + sp_trace_generateevent 15757563 Объясню, чем мне не подходит sp_trace_generateevent: мне нужна информация не в реалтайме (в профайлере), а "задним числом", и притом структурированная. То, что прекрасно подходит для целей ДБА, не покроет потребностей бизнес-пользователя. Т.е. мне нужно отделять - Дату и время события - Уровень события (ERROR/INFO/WARNING.....) - Источник события (хранимая процедура) - Инициатор события : вызвавшая рабочая станция - Инициатор события : вызвавший пользователь - Инициатор события : вызвавшее приложение - По возможности: идентификатор бизнес-объекта - По возможности: тип бизнес-объекта - И только потом идет детальная информация о том, что случилось, в виде свободного текста. Типовые сценарии: - импортированный ранее из системы (А) документ (ID) при передаче в систему (B) выдал ошибку - просят посмотреть, почему месяц назад джоб поменял атрибут документа (ID): не вносил ли кто-то изменения, которые могли "спровоцировать" джоб - наконец, типовой сценарий: кто и когда менял документ (ID) Доставать такие данные из нетипизированных MEMO-полей, даже если там XML - очень долго и ненадежно в плане достоверности. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.03.2015, 11:57 |
|
||
|
И снова про автономные транзакции с помощью CLR
|
|||
|---|---|---|---|
|
#18+
StibrusДоставать такие данные из нетипизированных MEMO-полей , ..., очень долго и ненадежно в плане достоверности. Комментарий относится только к выделенному (не к задаче). можно быстро и удобно ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.03.2015, 12:37 |
|
||
|
И снова про автономные транзакции с помощью CLR
|
|||
|---|---|---|---|
|
#18+
StibrusОбъясню, чем мне не подходит sp_trace_generateevent: мне нужна информация не в реалтайме (в профайлере), а "задним числом", и притом структурированная. То, что прекрасно подходит для целей ДБА, не покроет потребностей бизнес-пользователя.StibrusДоставать такие данные из нетипизированных MEMO-полей, даже если там XML - очень долго и ненадежно в плане достоверности.Какой реалтайм? Какой профайлер? Какие MEMO-поля? Вы вообще о чем? Хоть пробовали читать, что такое event notification? Вот вам болванка для дальнейших упражнений: Код: sql 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. 26. 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. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. Использование: Код: sql 1. 2. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.03.2015, 01:07 |
|
||
|
И снова про автономные транзакции с помощью CLR
|
|||
|---|---|---|---|
|
#18+
invm, Благодарю. Есть подозрение, что для моих целей это "из пушки по воробьям", но с темой обязательно ознакомлюсь. Пригодится если не для текущего проекта, то для чего-то еще. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.03.2015, 22:02 |
|
||
|
И снова про автономные транзакции с помощью CLR
|
|||
|---|---|---|---|
|
#18+
Создал триггер по указанной технологии. Однако, получаю странные записи. пример триггера: Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. В результате я получаю XML для всех событий, кроме N'r1_delete', для которых у меня пустая строка почти всегда. Однако, когда я удаляю запись из SSMS (админ), то вижу полноценный XML. Возникает вопрос - почему для пользователей пусто, срабатывает триггер, но not exists (select * from inserted) понимается неверно? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.03.2015, 11:37 |
|
||
|
И снова про автономные транзакции с помощью CLR
|
|||
|---|---|---|---|
|
#18+
Владислав Колосов, Если бы not exists (select * from inserted) интерпретировалось неверно, вы бы вообще не получали r1_delete. Посмотрите профайлером, что реально приходит в данных события. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.03.2015, 11:53 |
|
||
|
И снова про автономные транзакции с помощью CLR
|
|||
|---|---|---|---|
|
#18+
Разбил на три триггера. Похоже, что MERGE активирует триггеры INSERT и UPDATE при вставке. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.03.2015, 13:12 |
|
||
|
И снова про автономные транзакции с помощью CLR
|
|||
|---|---|---|---|
|
#18+
Владислав КолосовПохоже, что MERGE активирует триггеры INSERT и UPDATE при вставке.Это документировано: https://technet.microsoft.com/en-us/library/bb510625(v=sql.105).aspx Trigger Implementation For every insert, update, or delete action specified in the MERGE statement, SQL Server fires any corresponding AFTER triggers defined on the target table Если у вас триггер на insert, update, delete и в merge есть ветки insert, update и delete, то триггер будет вызван трижды. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.03.2015, 14:13 |
|
||
|
|

start [/forum/topic.php?fid=46&msg=38891372&tid=1687077]: |
0ms |
get settings: |
10ms |
get forum list: |
16ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
183ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
58ms |
get tp. blocked users: |
1ms |
| others: | 265ms |
| total: | 550ms |

| 0 / 0 |
