2016-10-05 6 views
11

मेरी समस्या: डेटा का एक सेट मेरे स्थानीय मशीन/MySQL डेटाबेस पर काम करता है, लेकिन उत्पादन पर यह Duplicate entry for key 'PRIMARY' त्रुटि का कारण बनता है। जहां तक ​​मैं दोनों सेटअप बता सकता हूं समकक्ष हैं।"कुंजी प्राथमिक के लिए डुप्लिकेट प्रविष्टि" लेकिन एक ही डेटा के साथ, अन्य नहीं?

मेरा पहला विचार यह था कि यह एक संयोजन मुद्दा है, लेकिन मैंने जांच की है कि दोनों डेटाबेस में टेबल utf8_bin का उपयोग कर रहे हैं।

तालिका खाली हो जाती है और मैं कोड में .Distinct() कर रहा हूं, इसलिए कोई डुप्लिकेट प्रविष्टियां नहीं होनी चाहिए।

प्रश्न में तालिका:

CREATE TABLE `mytable` (
    `name` varchar(100) CHARACTER SET utf8 NOT NULL, 
    `appid` int(11) NOT NULL, 
    -- A few other irrelevant fields 
    PRIMARY KEY (`name`,`appid`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; 

Database.cs:

[DbConfigurationType(typeof(MySql.Data.Entity.MySqlEFConfiguration))] 
public class Database : DbContext 
{ 
    public DbSet<MyTable> MyTable { get; set; } 
    public static Database Get() 
    { 
     /* Not important */ 
    } 
    //etc. 
} 

MyTable.cs:

[Table("mytable")] 
public class MyTable : IEquatable<MyTable>, IComparable, IComparable<MyTable> 
{ 
    [Column("name", Order = 0), Key, Required, DatabaseGenerated(DatabaseGeneratedOption.None)] 
    public string Name 
    { 
     get { return _name; } 
     set { _name = value.Trim().ToLower(); } 
    } 

    private string _name; 

    [Column("appid", Order = 1), Key, Required, DatabaseGenerated(DatabaseGeneratedOption.None)] 
    public int ApplicationId { get; set; } 

    //Equals(), GetHashCode(), CompareTo(), ==() etc. all auto-generated by Resharper to use both Name and ApplicationId. 
    //Have unit-tests to verify they work correctly. 
} 

फिर इसे का उपयोग:

using(Database db = Database.Get()) 
using(DbContextTransaction transaction = db.Database.BeginTransaction(IsolationLevel.ReadUncommitted)) 
{ 
    IEnumerable<MyTable> newEntries = GetNewEntries(); 
    //Verify no existing entries already in the table; not necessary to show since table is empty anyways 
    db.MyTable.AddRange(newEntries.Distinct()); 
} 

मुझे utf8_bin का उपयोग करते समय कोड में .Distinct() करने के बाद डेटाबेस में डुप्लिकेट प्रविष्टियां हो सकती हैं, खासकर जब से यह एक मशीन पर काम करती है लेकिन दूसरी नहीं। क्या किसी के पास कोई विचार है?

+0

'Distinct' के बारे में एक संबंधित सवाल: [अलग LINQ के साथ वस्तुओं के लिए काम नहीं कर रहा] (http://stackoverflow.com/q/1365748/4519059);)। –

+4

शायद यह कोड चलने वाली मशीनों की वर्तमान संस्कृति से संबंधित है। स्ट्रिंग समानता तुलना मौजूदा संस्कृति पर निर्भर करती है, इसलिए अलग-अलग सर्वरों पर अलग-अलग परिणाम उत्पन्न कर सकते हैं। फिर, जिन नामों को वर्तमान संस्कृति के साथ .NET द्वारा अलग माना जाता है उन्हें MySQL द्वारा समान माना जाता है और आपको उल्लंघन मिलता है। तो, दोनों मशीनों की भाषा सेटिंग्स की जांच करने का प्रयास करें, और यदि यह वास्तव में समस्या है - स्ट्रिंग तुलनाओं में समान संस्कृति का उपयोग करें। – Evk

+0

क्या आप असामान्य मानों का उदाहरण दे सकते हैं? दोनों मशीनों से। –

उत्तर

0

मैंने इसे this solution के समान, यूनिकोड-एस्केपिंग गैर-असीसी वर्णों द्वारा हल करने का अंत किया।

हालांकि, मैं अभी भी पता नहीं क्यों यह संभवतः हो सकता था ...

+0

हो सकता है क्योंकि ASCII "qwerty ????" "qwerty ????" के समान है, जब यूटीएफ में यह "qwertyАБВГ" और "qwertyЙЦУК" जैसे एक अलग तार है? – gaRex

0

दोनों एक ही डेटाबेस ड्राइवर का उपयोग कर मशीनों हैं है? जब विभिन्न ड्राइवर स्थापित होते हैं तो मेरे पास ईएफ और ओरेकल के साथ समान समस्याएं होती हैं।

संपादित करें:

इस दस्तावेज़

https://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html

का कहना है कि MySQL के 5.5.3 से पहले यूनिकोड वर्ण चरित्र प्रति 3 बाइट्स की एक अधिकतम उपयोग करके संग्रहीत किया गया है, और के बाद 4 बाइट का उपयोग कर संग्रहीत किया गया। यह इस बात को समझा सकता है कि एक कुंजी अद्वितीय होने के लिए निर्धारित है या नहीं। जब अंतर 'पूरक पात्र' का उपयोग पुराने संस्करणों के रूप में किया जाता है तो अंतर उस खेल को स्टोर नहीं कर सका।

क्या आपके दो डेटाबेस विभाजन के विभिन्न किनारों पर हैं (MySQL 5.5.3)?

+0

वही चालक, लेकिन विभिन्न डेटाबेस संस्करण। शायद यह एक MySQL बग है जो तय किया गया था? –

+0

मेरे मामले में ओरेकल 12 चालक को एक मशीन पर चलाना और ओरेकल 11 जी के खिलाफ ओरेकल 11 ड्राइवर दूसरे पर चल रहा था जिस तरह से संख्याओं को संसाधित किया गया था। एक सेटअप ने एक int वापस कर दिया, जहां दूसरा एक लंबा लौटा। यदि संभव हो, तो आपको अपने स्थानीय और परीक्षण/प्रोड वातावरण में एक ही संस्करण चलाया जाना चाहिए। –

+0

पुन: संपादित करें: उस लिंक के अनुसार 4-बाइट यूटीएफ 8 वर्ण एक नए चरित्र सेट, 'utf8mb4' का उपयोग करके संग्रहीत किए जाते हैं। जैसा कि आप कहते हैं, उन्होंने नहीं किया, 'utf8' अक्षर-सेट को बदलें जो मेरे दोनों डेटाबेस उपयोग कर रहे हैं। –

1

मैं निम्नलिखित बातों की जांच करेगा:

  • जांच दोनों मशीनों पर सटीक MySQL संस्करण। डुप्लिकेट पंक्ति के लिए, डेटा को एन्कोड किए जाने के तरीके के लिए आप SHOW VARIABLES LIKE "%version%";
  • SELECT HEX(name) का उपयोग करके MySQL क्लाइंट में ऐसा कर सकते हैं।
  • की जांच करता है, तो "UTF8" डेटा utf8mb3 या utf8mb4 में संग्रहित है

https://dev.mysql.com/doc/refman/5.7/en/charset-unicode-utf8mb3.html

https://dev.mysql.com/doc/refman/5.7/en/charset-unicode-utf8mb4.html

यह मानते हुए कि देव मशीन पर, डेटा स्थापित एक ताजा से डाला जाता है, और उस पर उत्पादन मशीन, डेटा को पुराने संस्करण के साथ सम्मिलित किया जा सकता था और फिर सर्वर को अपग्रेड किया गया था, अपग्रेड प्रक्रिया को सही तरीके से पूरा करने के लिए कार्रवाइयों की आवश्यकता होती है (और किया गया था) मैं विशेष रूप से जांचता हूं।

विशेष रूप से, MySQL संदर्भ मैनुअल में इन वर्गों (उचित संस्करण के लिए) देखें:

https://dev.mysql.com/doc/refman/5.7/en/checking-table-incompatibilities.html

यदि आवश्यक हो, अनुक्रमित के पुनर्निर्माण।

https://dev.mysql.com/doc/refman/5.7/en/rebuilding-tables.html

संपादित करें (2016-10-12)

सभी उपरोक्त तालिका पर केंद्रित है, और भंडारण पर।

ग्राहक और सर्वर के बीच कनेक्शन, character_set_connection जैसे चर के साथ कनेक्शन का एक और हिस्सा है।

कृपया तुलना करने के लिए सभी वर्ण सेट संबंधित सिस्टम चर जांचें।

mysql> show variables like "%character%"; 
+--------------------------+-------------------------------------------+ 
| Variable_name   | Value          | 
+--------------------------+-------------------------------------------+ 
| character_set_client  | utf8          | 
| character_set_connection | utf8          | 
| character_set_database | latin1         | 
| character_set_filesystem | binary         | 
| character_set_results | utf8          | 
| character_set_server  | latin1         | 
| character_set_system  | utf8          | 
| character_sets_dir  | /home/malff/GIT_TRUNK/sql/share/charsets/ | 
+--------------------------+-------------------------------------------+ 
8 rows in set (0.02 sec) 
-1

मैं यह हो सकता है क्योंकि कुछ वर्णों वातावरण के आधार पर अलग अलग अर्थ है, तो यह आम तौर पर अनुशंसित है कि आप इन विशेष वर्णों से पहले एक स्ट्रिंग एक डेटा मान के रूप में प्रयोग किया जाता है से बचने के बारे में सोचो।

चेक इस बाहर: http://dev.mysql.com/doc/refman/5.7/en/string-literals.html#character-escape-sequences

+0

? ऐसी कोई स्थिति नहीं है जहां यह एक समस्या हो सकती है। ईएफ ड्राइवर को किसी भी चरित्र से पारदर्शी रूप से बचना चाहिए जो अन्यथा किसी समस्या का कारण बनता है। –

+0

यह चाहिए। अब, क्या यह है? मैं सुझाव दूंगा कि आप इसे दोबारा करने के लिए कुछ चीजों को आजमाएं। 1) अपनी कुंजी पर एक मैनुअल diff करें और 2) अपनी कुंजी में विशेष पात्रों की तलाश करें। देखें कि क्या आप कुछ ढूंढ सकते हैं तो उन मानों का उपयोग करके त्वरित परीक्षण चलाएं और देखें कि क्या यह शिकायत करता है या नहीं। – JuanR

संबंधित मुद्दे