mysql DuplicateKeyException异常与DataIntegrityViolationException

775 阅读4分钟

数据库事务

在InnoDB引擎中,事务是一组逻辑上相关联的操作,它们要么全部成功执行,要么全部失败回滚。InnoDB引擎支持ACID属性,即:

  • 原子性(Atomicity):事务是不可分割的工作单位,事务中的所有操作要么全部完成,要么全部不完成,不会出现事务执行了一半就停止的情况。
  • 一致性(Consistency):事务在执行前后数据库中的数据保持一致状态,即事务结束时不管成功还是失败,数据库都必须回到原来的一致状态。
  • 隔离性(Isolation):不同的事务在并发执行时,彼此之间是隔离的,一个事务不能看到另一个事务中未提交的数据。
  • 持久性(Durability):事务一旦提交,其修改的数据就必须永久保存在数据库中,即使系统故障也不会丢失。

InnoDB引擎中默认的隔离级别为REPEATABLE READ,它能够保证在一个事务中,查询到的数据是一致的,并且不受其他并发事务的影响。InnoDB引擎支持多版本并发控制(MVCC),通过记录行的修改版本来实现读写并发。

在InnoDB引擎中,事务的使用非常方便,只需要在需要进行事务操作的语句前后加上BEGIN和COMMIT语句,例如:

BEGIN;
UPDATE table SET column = value WHERE condition;
INSERT INTO table (column1, column2) VALUES (value1, value2);
DELETE FROM table WHERE condition;
COMMIT;

在以上示例中,BEGIN语句表示开始事务,COMMIT语句表示提交事务,事务中的所有语句都必须遵循ACID属性。如果在事务中出现了错误,可以使用ROLLBACK语句回滚事务。

事务的隔离级别

事务隔离级别是指当多个事务同时访问数据库中相同数据时,数据库如何保证事务间的数据安全和一致性。常见的事务隔离级别有以下四种:

  1. READ UNCOMMITTED(读未提交):允许一个事务读取另一个未提交的事务的数据,可能会发生脏读、不可重复读、幻读的问题。

  2. READ COMMITTED(读已提交):保证一个事务提交后,另一个事务才能访问到提交的数据。可能会发生不可重复读、幻读的问题。

  3. REPEATABLE READ(可重复读):保证在同一个事务中访问同一数据时,多次读取的结果是一致的。可能会发生幻读的问题。

  4. SERIALIZABLE(串行化):将事务串行执行,避免了以上三种问题的发生,但是影响了并发访问性能。

不同的隔离级别会影响事务并发性能和数据一致性,需要根据实际场景进行选择。一般情况下,使用较高的隔离级别会提高数据的准确性,但会降低并发性能。而低隔离级别则可能出现数据的不一致性。 在InnoDb引擎中,事务的隔离级别为可重复读

唯一索引检查时间点

在InnoDB引擎中,唯一索引冲突的检查时间取决于是否存在事务以及事务的隔离级别。

如果没有开启事务,那么唯一索引冲突会在insert语句执行时检查,如果违反唯一约束,则会立即抛出DuplicateKeyException异常。

如果开启了事务,那么唯一索引冲突的检查时间会受到事务隔离级别的影响。例如,在隔离级别为REPEATABLE READ或SERIALIZABLE时,唯一索引冲突会在commit事务时进行检查,如果违反唯一约束,则会抛出DataIntegrityViolationException异常。而在隔离级别为READ UNCOMMITTED或READ COMMITTED时,唯一索引冲突会在insert语句执行时进行检查,如果违反唯一约束,则会立即抛出DuplicateKeyException异常。

因此,在InnoDB引擎中,无法显式地指定唯一索引冲突的检查时间,而是受到事务隔离级别的影响。如果需要在insert时检查唯一索引,可以使用隔离级别为READ UNCOMMITTED或READ COMMITTED的事务;如果需要在commit时检查唯一索引,可以使用隔离级别为REPEATABLE READ或SERIALIZABLE的事务。