我的问题:在我的本地计算机/ 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());
}
在使用.Distinct()
时,在代码中执行utf8_bin
之后,我不知道数据库中是否存在重复条目,尤其是因为它可以在一台计算机上运行而不能在另一台计算机上运行。有没有人有任何想法?
答案 0 :(得分:1)
我会调查以下几点:
SHOW VARIABLES LIKE "%version%";
SELECT HEX(name)
查看数据的编码方式,重复行。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 :(得分:0)
我最终通过unicode转义非ascii字符来解决它,类似于this solution。
但是,我仍然不知道为什么这可能发生......
答案 2 :(得分:0)
这两台机器是否使用相同的数据库驱动程序?安装不同的驱动程序时,我遇到了与EF和Oracle类似的问题。
编辑:
本文件
https://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html
说在MySQL 5.5.3之前,每个字符最多使用3个字节存储Unicode字符,之后使用4个字节存储。这可以解释密钥是否被确定为唯一的差异。当补充字符&#39;时,差异就会发挥作用。用作旧版本根本无法存储这些字符。
你的两个数据库是否存在鸿沟的不同方面(MySQL 5.5.3)?
答案 3 :(得分:-1)
我认为这可能是因为某些字符具有基于环境的不同含义,因此通常建议您在将字符串用作数据值之前转义这些特殊字符。
检查出来:http://dev.mysql.com/doc/refman/5.7/en/string-literals.html#character-escape-sequences