SQL सर्वर 2014 पर सीएलआर क्रैशिंग (विंडोज़ 2012R2)


12

मेरे पास यह छोटा सीएलआर है जो कॉलम में एक स्ट्रिंग पर एक रेजेक्स फ़ंक्शन करता है।

जब Windows Server 2012R2 पर SQL Server 2014 (12.0.2000) पर चल रहा है, तो प्रक्रिया क्रैश हो जाती है

Msg 0, स्तर 11, राज्य 0, लाइन 0 वर्तमान कमांड पर एक गंभीर त्रुटि हुई। यदि कोई परिणाम हैं, तो उनकी उपेक्षा की जानी चाहिए।

और अगर मैं करता हूं तो एक स्टैक डंप देता है

select count (*) from table where (CLRREGEX,'Regex')

लेकिन जब मैं करता हूं

select * from table where (CLRREGEX,'Regex') 

यह पंक्तियों को लौटाता है।

विंडोज 8.1 पर चलने वाले एक ही SQL सर्वर बिल्ड पर पूरी तरह से काम करता है।

कोई विचार?

- संपादित करें यह जितना आसान हो सकता है

using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SqlTypes;           //SqlString, SqlInt32, SqlBoolean
using System.Text.RegularExpressions; //Match, Regex
using Microsoft.SqlServer.Server;     //SqlFunctionAttribute
public partial class UserDefinedFunctions
{
    public static readonly RegexOptions Options = RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline;
    [SqlFunction]
    [Microsoft.SqlServer.Server.SqlFunction(IsDeterministic = true, IsPrecise = true)]
    public static SqlBoolean RegExMatch(SqlString input, SqlString pattern)
    {
        if (input.IsNull || pattern.IsNull) //nulls dont qualify for a match
            return SqlBoolean.False;
    return Regex.IsMatch(input.Value, pattern.Value, RegexOptions.IgnoreCase);
    }
}

इसलिए थोड़े से बदलावों से अब यह काम करता है: C # में मुख्य सबक टीएसक्यूएल के समान है जो अंतर्निहित डेटा रूपांतरण से सावधान है।

using System;
using System.Text;
using System.Data.SqlTypes;           //SqlString, SqlInt32, SqlBoolean
using System.Text.RegularExpressions; //Match, Regex
using Microsoft.SqlServer.Server;     //SqlFunctionAttribute
public partial class UserDefinedFunctions
{
public static readonly RegexOptions Options = RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant;

    [Microsoft.SqlServer.Server.SqlFunction(IsDeterministic = true, IsPrecise = true, DataAccess = DataAccessKind.Read)]
    public static SqlBoolean RegExMatch(SqlString input, SqlString pattern)
{
    if (input.IsNull || pattern.IsNull) //nulls dont qualify for a match
        return SqlBoolean.False;
    string sqldata = input.ToString();
    string regex = pattern.ToString();
    return Regex.IsMatch(sqldata, regex);
 }

क्या यह सभी पैटर्न या सिर्फ एक के लिए होता है? यह एक अकुशल पैटर्न (यानी अत्यधिक बैकट्रैकिंग या अनावश्यक कैप्चर) हो सकता है। आपको MatchTimeout प्रॉपर्टी (नए .NET फ्रेमवर्क 4.5 में नए) को सेट करना चाहिए । क्या आपने RegEx फ़ंक्शन को स्वयं कोड किया? यदि हां, तो क्या आप स्थिर या उदाहरण RegEx विधियों का उपयोग कर रहे हैं? है SqlFunctionविधि के रूप में चिह्नित IsDeterministic=true? विधानसभा के रूप में चिह्नित है SAFE?
सोलोमन रटज़की

2
ये टेबल कितने बड़े हैं? इसके अलावा, क्या आप जांच सकते हैं कि समस्या बयानों के लिए अनुमानित योजना में एक समानांतर ऑपरेटर है? यदि हाँ, तो क्या आप देख सकते हैं कि समस्या बिना समानता के होती है यानी MAXDOP = 1 संकेत के साथ।
अमित बैनर्जी

2
डुप्लिकेट [SqlFunction]विशेषता को छोड़कर, कोड ठीक दिखता है । क्या यह सटीक कोड है? मुझे नहीं लगता कि यह संकलन होगा। फ्रेमवर्क संस्करण 2.0 / 3.0 / 3.5 भेद एक गैर-मुद्दा है क्योंकि आप 4.0 / 4.5 / 4.5.x / etc का उपयोग कर रहे हैं या जो कुछ भी उस सर्वर पर है क्योंकि आप SQL सर्वर 2014 पर हैं जो CLR संस्करण 4 से बंधा है। सर्वर 32-बिट समस्या दिखा रहा है? अन्य सर्वरों की तुलना में इसमें कितनी मेमोरी है? और क्या आपने उस त्रुटि को प्राप्त करने के बाद SQL सर्वर लॉग की जाँच की है?
सोलोमन रटज़की

2
.NET का सटीक संस्करण समस्या से संबंधित नहीं है, हालांकि यह जानना अच्छा होगा कि सभी सर्वर कम से कम 4.5 पर हैं क्योंकि इसका मतलब है कि आप नई MatchTimeoutसंपत्ति का उपयोग कर सकते हैं। लेकिन मुझे नहीं लगता कि यह वास्तव में मुद्दा है या तो यदि आप केवल 5 वर्ण अधिकतम में गुजर रहे हैं। यह है संभव यह एक मशीन एक .NET फ्रेमवर्क के स्थापित भ्रष्ट है, और है कि एक बार ट्राउट मछली पकड़ने की गतिविधियों रह गए है ;-) ठीक किया जा सकता। इसके अलावा, [0-9].*सरल लेकिन यह भी अक्षम है क्योंकि यह सभी अंकों से मेल खाता है, यदि कोई है, तो पहले अंक के बाद; सिर्फ [0-9]एक के लिए उपयोग IsMatchकरना बेहतर है।
सोलोमन रटज़की

1
आप क्यों बदल DataAccessKindगए Read? यह सिर्फ इसे धीमा कर देता है और आप कोई डेटा एक्सेस नहीं कर रहे हैं। इसके अलावा, मुझे एहसास है कि यह अब काम कर रहा है, लेकिन मैं संपत्ति के ToString()विपरीत विधि का उपयोग करने के साथ सतर्क Valueरहूंगा क्योंकि मुझे नहीं लगता कि ToString ठीक से एन्कोडिंग को संभालती है, या ऐसा कुछ। आपके डेटाबेस से क्या टकराव तय है? बेशक, मैं अभी आपकी एक टिप्पणी ऊपर पढ़ता हूं और देखता हूं कि स्तंभ NVARCHAR के बजाय VARCHAR है। क्या उस फ़ील्ड का डेटाबेस से अलग कॉलेशन है?
सोलोमन रटज़की ने

जवाबों:


4

समस्या विंडोज ओएस और एसक्यूएल सर्वर (विशेष रूप से डेटाबेस जहां विधानसभा भरी हुई है) के बीच एक स्थानीय संघर्ष है। आप निम्नलिखित क्वेरी को यह देखने के लिए चला सकते हैं कि वे दोनों किसके लिए निर्धारित हैं:

SELECT os_language_version,
       DATABASEPROPERTYEX(N'{name of DB where Assembly exists}', 'LCID') AS 'DatabaseLCID'
FROM   sys.dm_os_windows_info;

यदि वे अलग हैं तो आप निश्चित रूप से कुछ "अजीब" व्यवहार प्राप्त कर सकते हैं, जैसे कि आप क्या देख रहे हैं। मुद्दा यह है कि:

  • SqlStringइसमें केवल पाठ से अधिक शामिल है: इसमें डेटाबेस का डिफ़ॉल्ट कोलाजेशन शामिल है जिसमें विधानसभा मौजूद है। टकराव जानकारी के दो टुकड़ों से मिलकर बनता है: स्थानीय जानकारी (यानी LCID), और तुलना विकल्प (यानी SqlCompareOptions) जो मामले, लहजे, काना, चौड़ाई, या सब कुछ (बाइनरी और बाइनरी 2) की संवेदनशीलता को विस्तार से बताता है।
  • .NET में स्ट्रिंग संचालन, जब तक कि स्पष्ट रूप से एक लोकेल नहीं दिया जाता है, वर्तमान थ्रेड की स्थानीय जानकारी का उपयोग करें, जो विंडोज (यानी ऑपरेटिंग सिस्टम / ओएस) में सेट है।

विरोध आमतौर पर तब होता है जब SqlString पैरामीटर का उपयोग किए बिना .Valueया .ToString()ऐसे कि यह एक अंतर्निहित रूपांतरण करता है SqlString। उस स्थिति में यह अपवाद का कारण होगा कि LCID मैच नहीं करते हैं।

स्पष्ट रूप से अन्य परिदृश्य हैं, जैसे कि प्रदर्शन (कुछ / सभी?) स्ट्रिंग तुलना, जिसमें रेक्स का उपयोग करना शामिल है क्योंकि यह मामला दिखाता है (हालांकि अभी तक मैं इसे पुन: पेश करने में सक्षम नहीं हुआ हूं)।

सुधार के लिए कुछ विचार:

आदर्श (अपेक्षा हमेशा मिलेंगे कि तुलना कैसे काम करती है):

  • Windows या SQL सर्वर LCID (डिफ़ॉल्ट भाषा) को बदलें ताकि दोनों मेल खाएं

आदर्श से कम (विंडोज लोकेल का व्यवहार समानता और छंटाई के लिए समान नियम नहीं हो सकता है और इसलिए अप्रत्याशित परिणाम हो सकते हैं):

  • .ToStringविधि या .Valueसंपत्ति का उपयोग करें , जो दोनों SQL सर्वर LCID के बिना स्ट्रिंग लौटाते हैं, इसलिए सभी ऑपरेशन OS LCID का उपयोग करेंगे।

मदद हो सकती है:

  • शायद SqlCharsइसके बजाय का उपयोग करें SqlStringक्योंकि यह SQL सर्वर से LCID और टकराव की जानकारी को साथ नहीं लाता है
  • निर्दिष्ट करें कि संस्कृति इसके माध्यम से मायने नहीं रखती है StringComparison.InvariantCulture:
    • String.Compare(string, string, StringComparison.InvariantCulture) या String.Compare(string, string, StringComparison.InvariantCultureIgnoreCase)
    • रेगेक्स के लिए, निर्दिष्ट करें RegexOptions.CultureInvariant

1

अपडेट किया गया ..

SQL इंजन और विंडो सर्वर के बीच @srutzky बताते हुए स्थानीयकरण अलग है:

os_language_version SqlServerLCID
1033 1039

कोड में निम्नलिखित परिवर्तन - विकल्प सेट RegexOptions.CultureInvariantकरना त्रुटि के आसपास हो जाता है। अपरिवर्तित कोड एक ही भाषा सेटिंग्स के साथ विंडोज सर्वर 2012R2 पर SQL सर्वर 2012 को क्रैश नहीं करेगा, लेकिन SQL सर्वर 2014 पर ऐसा करता है।

using System;
using System.Text;
using System.Data.SqlTypes;           //SqlString, SqlInt32, SqlBoolean
using System.Text.RegularExpressions; //Match, Regex
using Microsoft.SqlServer.Server;     //SqlFunctionAttribute
public partial class UserDefinedFunctions
{
public static readonly RegexOptions Options = RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant;

    [Microsoft.SqlServer.Server.SqlFunction(IsDeterministic = true, IsPrecise = true)]
    public static SqlBoolean RegExMatch(SqlString input, SqlString pattern)
{
    if (input.IsNull || pattern.IsNull) //nulls dont qualify for a match
        return SqlBoolean.False;
    string sqldata = input.ToString();
    string regex = pattern.ToString();
    return Regex.IsMatch(sqldata, regex);
 }

आप कृपया सर्वर है कि दुर्घटनाग्रस्त हो गया था पर निम्नलिखित चला सकते हैं: SELECT os_language_version, SERVERPROPERTY('LCID') AS 'SqlServerLCID' FROM sys.dm_os_windows_info;। यह काफी संभव है कि मुद्दा भाषा सेटिंग में एक संघर्ष था। आपका समाधान अभी भी जाने का सबसे अच्छा तरीका हो सकता है, लेकिन आम तौर पर एस पर संपत्ति के ToString()बजाय उपयोग करने की आवश्यकता नहीं होनी चाहिए । इसलिए स्थिति की पुष्टि करना अच्छा होगा। ValueSqlString
सोलोमन रटज़की

मैंने स्पष्ट करने के लिए एक उत्तर पोस्ट किया है, लेकिन समस्या को तब तक हल नहीं किया जाना चाहिएRegexOptions.CultureInvariant क्योंकि आप Optionsचर को पास नहीं करते हैं Regex.IsMatch(sqldata, regex)। वह चीज़ जो आपके मूल कोड और नए, काम करने वाले कोड के बीच बदल गई है, जिसका उपयोग SqlString.Valueकरने से आप गए हैं SqlString.ToString()। मुझे संदेह है कि यदि आपने उपयोग करना बंद कर दिया है तो आपको वही निश्चित व्यवहार दिखाई देगा SqlChars। लेकिन मैं सिर्फ एक परीक्षा के रूप में ऐसा करूंगा। सबसे अच्छा तरीका यह है कि दूसरे से मिलान करने के लिए या तो विंडोज या SQL सर्वर के LCID को बदलें। आप विकल्प स्थिर चर भी निकाल सकते हैं।
सोलोमन रटज़की

नमस्ते। मेरा उत्तर स्वीकार करने के लिए धन्यवाद :)। बस उल्लेख करने के लिए, मैंने आगे अनुसंधान किया और, अगर मैं जो देख रहा था उसे समझ गया, तो जब मैं मूल कारण ओएस और एसक्यूएल सर्वर के बीच एक अलग एलसीआईडी ​​होने के बारे में सही हूं, तो यह .Valueसंपत्ति से संबंधित नहीं है या नहीं होना चाहिए एक की SqlStringहै कि के रूप में जाहिरा तौर पर के रूप में ही आंतरिक मान देता है .ToString()विधि। मैं अभी भी जांच कर रहा हूं और जो कुछ भी मुझे मिल रहा है उसके साथ अपने जवाब को अपडेट करूंगा :)।
सोलोमन रुट्ज़की

मैंने नई जानकारी के प्रकाश में अपना उत्तर समायोजित किया। मैं इस परिदृश्य को पुन: पेश नहीं कर सकता। प्रश्न में कोड वास्तव में आप क्या थे / उपयोग कर रहे हैं? उनके बीच एकमात्र वास्तविक अंतर यह है कि एक त्रुटि का उपयोग करता है RegexOptions.IgnoreCaseजबकि दूसरा नहीं करता है। मैंने एक समान वातावरण सेट किया है: Windows (8.0) 1033 के LCID का उपयोग करते हुए, SQL सर्वर DB का 1039 का LCID है, उसी RegEx का उपयोग करके जिसे आपने पोस्ट किया है, GUID से भरे क्षेत्र COUNT(*)पर VARCHAR, एक पैटर्न का उपयोग करके '[0-3â].*', एक टेबल पर। 10 मिलियन पंक्तियों के साथ। यह SQL Server 2012 है, न कि 2014, हालांकि मुझे नहीं लगता कि इससे कोई फर्क नहीं पड़ता।
सोलोमन रटज़की

1
सारे सवालों के जवाब देने के लिए धन्यवाद। प्रश्न में कोड वह है जो मैं उपयोग कर रहा था। मेरे पास वास्तव में जटिल रेगेक्स था, लेकिन यह एक बहुत ही सरल का उपयोग करके क्रैश करने में कामयाब रहा। RegexOptions.CultureInvariant सेटिंग्स बदलने से व्यवहार बंद हो गया
Spörri
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.