我的问题是:插入一组数据在我的本地机器/mysql数据库上工作,但在生产上它会导致 Duplicate entry for key 'PRIMARY'
错误。据我所知,这两种设置是等效的。
我的第一个想法是这是一个排序规则问题,但我检查了两个数据库中的表是否都在使用 utf8_bin
.
table一开始是空的,我正在做 .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 { 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());
}
我不知道在做了一个测试之后,数据库中怎么会有重复的条目 .Distinct()
在代码中,使用 utf8_bin
尤其是因为它在一台机器上工作,而不是在另一台机器上。有人有什么想法吗?
4条答案
按热度按时间bt1cpqcv1#
我将调查以下几点:
在两台机器上检查mysql的确切版本。您可以在mysql客户机中使用
SHOW VARIABLES LIKE "%version%";
使用SELECT HEX(name)
查看数据是如何编码的,对于重复行。调查“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
假设在dev机器上,数据是从新安装插入的,而在生产机器上,数据可能是使用旧版本插入的,然后服务器升级的,我将特别检查是否需要(并且已经完成)操作来正确完成升级过程。
特别是,请参阅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)
所有这些都集中在table和存储上。
要检查的另一部分是客户机和服务器之间的连接,包括
character_set_connection
.请检查所有字符集相关的系统变量,以进行比较。
w1e3prcc2#
我最终通过unicode转义非ascii字符来解决这个问题,类似于这个解决方案。
然而,我仍然不知道为什么会发生这种事。。。
nsc4cvqm3#
两台机器是否使用相同的数据库驱动程序?当安装不同的驱动程序时,ef和oracle也有类似的问题。
编辑:
本文件
https://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html
在MySQL5.5.3Unicode之前,每个字符最多存储3个字节,而在MySQL5.5.3Unicode之后,每个字符最多存储4个字节。这可以解释一个键是否被确定为唯一的区别。当使用“补充字符”时,这种差异就会发挥作用,因为旧版本根本无法存储这些字符。
您的两个数据库是否处于不同的界限(mysql 5.5.3)?
2eafrhcq4#
我认为这可能是因为某些字符在不同的环境下有不同的含义,所以通常建议您在将字符串用作数据值之前转义这些特殊字符。
看看这个:http://dev.mysql.com/doc/refman/5.7/en/string-literals.html#character-转义序列