mysql主键设置成auto_increment时,进行并发性能测试出现主键重复Duplicate entry 'xxx' for key 'PRIMARY'

mysql主键设置成auto_increment时,进行并发性能测试出现主键重复Duplicate entry 'xxx' for key 'PRIMARY'

解决方法:

在my.cnf的[mysqld]片段中添加设置innodb_autoinc_lock_mode=0

同时注意调大jdbc的活跃链接数,如设置 jdbc.maxActive=300,因为设置innodb_autoinc_lock_mode=0可能导致链接过多。

注意,这种方式只需要在并发性能测试时设置,因为这种方式在插入记录时需进行全表锁定,性能较差,平时生产环境中只需使用默认的设置innodb_autoinc_lock_mode=1即可,mysql的官方文档有说明:


http://dev.mysql.com/doc/refman/5.6/en/innodb-auto-increment-configurable.html

innodb_autoinc_lock_mode属性的含义如下:

1、innodb_autoinc_lock_mode = 0 (“traditional” lock mode)
这种方式就和mysql5.1.22以前一样,这种方式的特点就是“表级锁定”,并发性较差


2、innodb_autoinc_lock_mode = 1 (“consecutive” lock mode)
这种方式是新版本中的默认方式,推荐使用,并发性相对较高,特点是“consecutive”,即保证同一条insert语句中新插入的auto_increment id都是连续的。
这种模式下:
“Simple inserts”:直接通过分析语句,获得要插入的数量,然后一次性分配足够的auto_increment id,只会将整个分配的过程锁住。
“Bulk inserts”:因为不能确定插入的数量,因此使用和以前的模式相同的表级锁定。
“Mixed-mode inserts”:直接分析语句,获得最坏情况下需要插入的数量,然后一次性分配足够的auto_increment id,只会将整个分配的过程锁住。需要注意的是,这种方式下,会分配过多的id,而导致”浪费“。比如INSERT INTO t1 (c1,c2) VALUES (1,’a'), (NULL,’b'), (5,’c'), (NULL,’d');会一次性的分配5个id,而不管用户是否指定了部分id;INSERT … ON DUPLICATE KEY UPDATE一次性分配,而不管将来插入过程中是否会因为duplicate key而仅仅执行update操作。
注意:当master mysql版本<5.1.22,slave mysql版本>=5.1.22时,slave需要将innodb_autoinc_lock_mode设置为0,因为默认的 innodb_autoinc_lock_mode为1,对于INSERT … ON DUPLICATE KEY UPDATE和INSERT INTO t1 (c1,c2) VALUES (1,’a'), (NULL,’b'), (5,’c'), (NULL,’d');的执行结果不同,现实环境一般会使用INSERT … ON DUPLICATE KEY UPDATE。


3、innodb_autoinc_lock_mode = 2 (“interleaved” lock mode)
这种模式是来一个分配一个,而不会锁表,只会锁住分配id的过程,和innodb_autoinc_lock_mode = 1的区别在于,不会预分配多个,这种方式并发性最高。但是在replication中当binlog_format为statement-based时 (简称SBR statement-based replication)存在问题,因为是来一个分配一个,这样当并发执行时,“Bulk inserts”在分配的时会同时向其他的INSERT分配,会出现主从不一致(从库执行结果和主库执行结果不一样),因为binlog只会记录开始的 insert id。

参考文档:

http://biancheng.dnbcw.info/mysql/356243.html

<think>好的,我现在需要帮助用户解决关于数据库实体完整性规则违反的问题。用户想知道错误的原因和解决方案。首先,我需要回忆一下实体完整性的基本概念。实体完整性主要是通过主键来确保每条记录的唯一性和非空性。违反这个规则的情况通常包括主键重复或者主键为空。 接下来,我要考虑用户可能的场景。用户可能是开发人员或者数据库管理员,遇到了插入或更新数据出现的错误,比如主键冲突或者空值问题。他们需要知道具体的原因以及如何解决这些问题。同,用户可能对如何预防这类问题感兴趣,比如在设计数据库应该注意什么,或者如何通过约束和触发器来加强完整性。 我需要参考已有的引用内容,特别是引用[4],里面提到了实体完整性的定义,主键必须唯一且非空,还提到了触发器的使用。例如,触发器可以用于检查年龄是否超过限制,类似的方法也可以用于确保主键的合法性。不过,主键通常由数据库自动管理,但用户可能在某些情况下手动设置主键,导致问题。 错误原因可能包括:主键字段重复插入相同的值,主键字段为NULL,并发操作导致主键冲突,或者数据库设计不当,比如主键选择不合适。解决方案方面,需要确保生成唯一主键,比如使用自增字段或UUID;设置主键字段为非空;处理并发问题,比如使用事务或者数据库的锁机制;以及合理设计主键,避免使用可能重复的业务字段。 此外,引用[2]和[3]提到了外键和删除操作的处理,虽然不直接相关,但可能对理解整体数据完整性有帮助。例如,外键约束的处理方式可能会影响相关表的数据,但实体完整性更关注主键本身。 用户可能还需要具体的例子,比如如何设置自增主键,或者如何用触发器捕获错误。例如,在MySQL中,可以使用AUTO_INCREMENT,而在PostgreSQL中使用SERIAL或IDENTITY类型。触发器可能在需要复杂检查使用,但主键的检查通常由数据库自动处理,所以触发器的例子可能需要调整。 可能还需要提到常见的错误信息,比如在尝试插入重复主键,数据库会抛出类似“Duplicate entry 'xxx' for key 'PRIMARY'”的错误,而插入NULL会提示主键不能为NULL。 总结下来,回答的结构应该是先解释违反实体完整性的原因,再分点列出解决方案,并结合实际例子和引用内容。需要确保语言清晰,结构合理,符合用户的要求,并且引用正确的来源,比如引用[4]中关于实体完整性和触发器的部分。</think>### 违反数据库实体完整性规则的原因及解决方法 #### 一、**违反实体完整性规则的原因** 1. **主键重复** 尝试插入或更新记录主键字段的值与表中已有记录的主键重复。例如,主键为 `student_id` 的表中,插入两条 `student_id=1001` 的记录会导致违反唯一性约束[^4]。 2. **主键为空(NULL)** 主键字段不允许为 NULL,如果插入或更新主键值为空,则会触发错误。例如: ```sql INSERT INTO Student (student_id, name) VALUES (NULL, '张三'); -- 错误! ``` 3. **并发操作冲突** 多线程或分布式系统中,未正确处理主键生成逻辑,可能导致重复主键。例如,多个客户端同插入数据未同步主键生成机制。 4. **设计缺陷** 主键选择不当(如使用可能重复的业务字段),导致无法保证唯一性。例如,用 `name` 作为主键,但存在同名用户。 --- #### 二、**解决方案** ##### 1. **确保主键唯一性** - **自动生成主键** 使用数据库自增字段(如 MySQL 的 `AUTO_INCREMENT`,PostgreSQL 的 `SERIAL` 或 `IDENTITY`)或 UUID: ```sql CREATE TABLE Student ( student_id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) ); ``` - **业务层校验** 在应用程序中检查主键是否已存在,再执行插入操作。 ##### 2. **禁止主键为 NULL** - 在表定义中明确主键非空约束: ```sql CREATE TABLE Student ( student_id INT NOT NULL PRIMARY KEY, name VARCHAR(50) ); ``` ##### 3. **处理并发问题** - **使用事务与锁** 在事务中结合 `SELECT ... FOR UPDATE` 锁定资源,避免并发插入冲突。 - **分布式唯一 ID 生成** 使用雪花算法(Snowflake)或数据库序列(Sequence)生成全局唯一主键。 ##### 4. **合理设计主键** - 避免使用业务字段(如身份证号、电话号码)作为主键,优先选择无意义的代理键(如自增 ID)。 - 复合主键需确保所有字段组合唯一。例如: ```sql CREATE TABLE Course_Selection ( student_id INT, course_id INT, PRIMARY KEY (student_id, course_id) -- 联合主键 ); ``` ##### 5. **错误捕获与提示** - 通过触发器或存储过程捕获错误,并返回友好提示。例如,使用触发器防止主键为空: ```sql CREATE TRIGGER Check_Primary_Key BEFORE INSERT ON Student FOR EACH ROW BEGIN IF NEW.student_id IS NULL THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '主键不能为空'; END IF; END; ``` --- #### 三、**典型案例** - **错误示例**: ```sql INSERT INTO Student (student_id, name) VALUES (1001, '李四'); -- 若 student_id=1001 已存在,报错:Duplicate entry '1001' for key 'PRIMARY' ``` - **解决方法**: 检查主键是否存在,或改用自增主键。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值