首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么插入两条相同的记录而事务不能回滚

在数据库中,事务是一组数据库操作的逻辑单元,要么全部执行成功,要么全部回滚到初始状态。当插入两条相同的记录时,事务不能回滚的原因如下:

  1. 主键冲突:数据库表通常会有一个主键,用于唯一标识每条记录。当插入两条相同的记录时,会导致主键冲突,违反了唯一性约束。数据库会抛出主键冲突的异常,事务会中断并不能回滚。
  2. 数据库引擎的实现:数据库引擎在执行插入操作时,会先将数据写入内存缓冲区,然后再写入磁盘。如果两条相同的记录在内存缓冲区中被认为是不同的记录,那么在写入磁盘时就不会触发主键冲突,因此事务也不会回滚。
  3. 事务的隔离级别:数据库事务有不同的隔离级别,如读未提交、读已提交、可重复读和串行化。在某些隔离级别下,数据库引擎可能会允许并发事务同时插入相同的记录,而不触发主键冲突。因此,即使插入了相同的记录,事务也不会回滚。

总结起来,插入两条相同的记录而事务不能回滚的原因主要是主键冲突和数据库引擎的实现方式。为了避免这种情况,开发人员应该在插入记录之前进行合适的校验,确保不会插入重复的数据。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

咦,为什么我的事务回滚不了?

MySQL 事务小伙伴们都懂,通过 begin 开启事务,通过 commit 提交事务或者通过 rollback 回滚事务。...这就意味着带有 DDL 语句的事务将来没有办法 rollback。 我举一个简单的例子,大家一起来看下: 我们来一起看下我这里的测试逻辑: 首先查询总记录数有四条。 开启一个事务。...回滚。 再次查询数据。 到第六步的时候,我们发现查询到的数据只剩三条了,说明第五步的回滚并没有生效。原因就在于执行 alter 之前,事务已经被隐式提交了。...对于上面的案例,如果大家去掉第四步的 alter,那么回滚是可以回滚成功的,这个小伙伴们自己来测试,我就不演示了。...我举个简单例子: 可以看到,跟第一小节的测试步骤一样,只不过第四步换成一个 GRANT 语句,那么最终的事务回滚也会失效,原因就在于事务已经提交了。

1K20

MySQL间隙锁(幻读解决原理)

设置事务为手动提交,然后把隔离级别设置成串行化 查看表结构,id、age、name都有索引 场景1:用不可重复的主键id测试间隙锁 范围查询 事务2的select操作只给三行数据加了共享锁,为什么插入...,就能防止幻读 场景2:用可重复的age(有索引)测试间隙锁 测试辅助索引树上,间隙锁的范围 我们先查看一下表结构、表数据,然后回滚 开启事务进行测试 很明显,由于age>20的区间都被事务1加上了间隙锁...回滚,然后启动事务 1....测试不能重复的主键索引 此时事务2 select,由于是等值查询,相当于给这条数据加上了共享锁 事务1现在插入新的数据是可以成功的,因为主键id不能重复,我们不能再插入主键id=9的数据 在这种情况下,...测试能重复的辅助索引 回滚并重启事务 事务2等值查询,给age=18这行数据加上共享锁(record-lock) 事务1插入age=18,这是不能允许的,否则事务2再查询age=18就有两条记录了(幻读

1.2K20
  • 事务控制

    在同一个事务操作中,最好使用相同存储引擎的表,如果使用不同存储引擎的表后,rollback 语句会对非事务类型的表进行特别处理,因此 commit 、rollback 只能对事务类型的表进行提交和回滚。...我们提交的事务一般都会被记录到二进制的日志中,但是如果一个事务中包含非事务类型的表,那么回滚操作也会被记录到二进制日志中,以确保非事务类型的表可以被复制到从数据库中。...对于回滚的话,还要讲一点就是 SAVEPOINT,它能指定事务回滚的一部分,但是不能指定事务提交的一部分。SAVEPOINT 可以指定多个,在满足不同条件的同时,回滚不同的 SAVEPOINT。...SAVEPOINT,如下所示 savepoint test; 然后继续插入一条记录 insert into cxuan005(id,info) values(777,'cxuan777'); 此时就可以查询到两条新增记录了...这个表,可以看到,只有 id=666 的这条记录插入进来了,说明 id=777 这条记录已经被回滚了。

    16030

    PostgreSQL的MVCC vs InnoDB的MVCC

    InnoDB中的MVCC 为了支持多版本,InnoDB对行记录又额外维护了几个字段: 1、DB_TRX_ID:插入或更新航记录的事务的事务ID 2、DB_ROLL_PTR:即回滚指针,指向回滚段中的undo...同理,第三步,删除T1然后将其标记为虚拟删除(仅在行记录指定的一个bit位上打上delete标签)并在回滚段中插入一个对应的新版本。同样回滚指针指向回滚段中undo log。...InnoDB的老版本存储到回滚段,且比对应的插入记录小,因为InnoDB仅将变化的值写到undo log。...2、INSERT操作 INSERT时,InnoDB会向回滚段写入额外的记录,而PostgreSQL仅在UPDATE中创建新版本。...3、回滚时恢复老版本 回滚时,PostgreSQL不用任何特定内容,需注意老版本的xmax等于update该记录的事务ID。因此在并发快照中该记录认为是alive的直到该事务ID的事务提交。

    1.2K10

    MySQL 核心模块揭秘 | 14 期 | 回滚整个事务

    回滚整个事务时,事务执行过程中改变(插入、更新、删除)的数据都不要了,产生的 binlog 日志也就没有用了。 回滚整个事务,首先要进行的步骤就是 binlog 回滚。...这其实取决于回滚操作是怎么进行的。 我最初理解的回滚操作,是把事务执行过程中改变(插入、更新、删除)的记录恢复原样,就像事务什么都没干过一样。 然而,实际情况没有这么理想。...事务执行过程中改变(插入、更新、删除)记录,会产生 binlog 日志。 回滚时,要把记录再修改回原来的样子。从逻辑上来看,记录就像是从来没有发生过变化,binlog 日志也就不需要了。...这是因为: 清空磁盘临时文件中 binlog 日志的过程不可逆,如果中间出现问题,不能回退。 InnoDB 回滚步骤中提交事务的容错性更好,回滚失败之后就不清除 binlog 日志了,也不损失什么。...第 2 步,执行 InnoDB 回滚操作,会把事务执行过程中改变(插入、更新、删除)的记录恢复原样(至少从逻辑上来看是这样的)。 最后,还会提交 InnoDB 事务,让回滚操作对数据页的修改生效。

    15110

    MySQL-锁总结

    A先执行,在10与20两条记录中插入了一行,还未提交: insert into t values(11, xxx); 事务B后执行,也在10与20两条记录中插入了一行: insert into...快照数据是指该行的之前版本的数据,该实现是通过undo段来完成。而undo用来在事务中回滚数据,因此快照数据本身是没有额外的开销。...与事务1相同,此时undo log中有2条记录,并且通过回滚指针连在一起。...超时机制虽然简单,但是其使用FIFO的方式来选择超时回滚的事务,假如第一个超时的事务 更新了很多行,远比第二个事务多,因此占用了更多的undo log,这时FIFO的方式,就显得不适用了,因为第一个事务回滚时间明显比第二个事务回滚时间长很多...在等待图中,事务为图中的节点。在图中,事务T1指向事务T2边的定义为: (1)事务T1等待事务T2所占用的资源 (2)事务之间在等待相同的资源,而事务T1在事务T2之后 ? ?

    93210

    Mysql死亡笔记的死锁记录

    MySQL如果检测到两个事务发生了死锁,会回滚其中一个事务,让另一个事务执行成功。很明显,我们这条insert语句被回滚了。...好在MySQL记录了最近一次的死锁日志,可以用命令行工具查看: show engine innodb status; 图片 在死锁日志中,可以清楚地看到这两条insert语句产生了死锁,最终事务2被会回滚...从死锁日志中,我们看到有两条insert语句,很明显userId=5和userId=6的数据都不存在。...所以对应的SQL执行过程,可能就是这样的: 图片 先用for update加上排他锁,防止其他事务修改当前数据,然后再insert数据,最后发生了死锁,事务2被回滚。...两个事务分别在两个主键ID上面加锁,为什么会产生死锁呢? 如果看过上篇文章,就会明白。

    40051

    Spring事物的传播行为案例分析

    隔离性(Isolation):不同事务同时进行某项业务,处理相同的数据时候,需要保证事务之间相互独立,互相之间数据不影响。...事务的传播特行为为required  结果是因为主键冲突将事务进行了回滚,所以两条数据都没有插入进去。...事务的传播行为为manatory  因为调用的外层没有事务,所以两条数据没有插入。大家想想下面这种写法会发生什么现象事务的传播行为mandatory ?...事务的传播行为required_new(代码注释清忽略)  结果和require一样,两条数据都没有入库,唯一健冲突导致第一条数据回滚,大家可以思考下我下面这两种情况。 ?...情景1新起的事务抛出异常会不会让外围事务回滚? ? 情景2外围事务失败会不会导致新起事务已提交的回滚?

    56910

    Spring事务的传播行为案例分析

    隔离性(Isolation):不同事务同时进行某项业务,处理相同的数据时候,需要保证事务之间相互独立,互相之间数据不影响。...required 结果是因为主键冲突将事务进行了回滚,所以两条数据都没有插入进去。...[qqq] 事务的传播行为为manatory 因为调用的外层没有事务,所以两条数据没有插入。...,重新执行新加的事务 [qqq] 事务的传播行为required_new 结果和require一样,两条数据都没有入库,唯一健冲突导致第一条数据回滚,大家可以思考下我下面这两种情况。...[qqq] 情景1新起的事务抛出异常会不会让外围事务回滚? [1596529877936016308.jpeg] 情景2外围事务失败会不会导致新起事务已提交的回滚?

    98110

    【JavaP6大纲】MySQL篇:传播行为

    外围方法未开启事务,插入用户表和用户角色表的方法在自己的事务中独立运行,外围方法异常不影响内部插入,所以两条记录都新增成功。...外围方法开启事务,内部方法加入外围方法事务,外围方法回滚,内部方法也要回滚,所以两个记录都插入失败。...,所以两条记录都新增成功。...外围方法开启事务,内部方法加入外围方法事务,外围方法回滚,内部方法也要回滚,所以两个记录都插入失败。...propagation_mandatory(强制传播):使用当前事务,如果没有则抛出异常 外围方法开启事务,内部方法加入外围方法事务,外围方法回滚,内部方法也要回滚,所以两个记录都插入失败。

    26010

    一篇文章彻底搞懂Mysql事务相关原理

    此锁发出插入意图的信号是,如果多个事务未插入间隙中的相同位置,则无需等待插入到同一索引间隙中的多个事务。假设存在索引记录,其值分别为4和7。...回滚段中的撤消日志分为插入和更新撤消日志。插入撤消日志仅在事务回滚时才需要,并且在事务提交后可以立即将其丢弃。...InnoDB仅在丢弃为删除而编写的更新撤消日志记录时,才物理删除相应的行及其索引记录。此删除操作称为purge,它非常快,通常花费与执行删除操作的SQL语句相同的时间顺序。...思考:为什么先写日志后写数据库?---稍后做解释 根据undo log 进行回滚 为了做到同时成功或者失败,当系统发生错误或者执行rollback操作时需要根据undo log 进行回滚 ?...如果SELECT调用在事务中调用了存储的函数,而该函数内的一条语句失败,则该语句将回滚。此外,如果 ROLLBACK在此之后执行,则整个事务都会回滚。

    85310

    MySQL是怎么保证数据一致性的

    下边就介绍InnoDB的事务模型 MySQL官方文档对事务是这么描述的“事务是可以提交或回滚的原子工作单元。当事务对数据库进行多个更改时,要么提交事务时所有更改都成功,要么回滚事务时撤消所有更改。”...包含一个随着新行插入而单调增加的行ID,如果innodb自动生成聚集索引,则该索引包含行ID值。否则,DB_ROW_ID列不会出现在任何索引中。...2、多版本产生过程 以新增一条记录并对该记录进行2次修改来说明具体实现 ? 这条记录有3个隐含字段(前面已经介绍),分别应对行的ID、事务号和回滚指针。...当插入的是一条新数据时,记录上对应的回滚段指针为NULL ?...3、提交与回滚 当事务正常提交时,InnoDB只需要更改事务状态为commit即可,不需要做其他额外的工作 回滚(rollback)需要根据当前回滚指针从Undo Log中找出事务修改前的版本,并恢复。

    4K10

    JDBC事务控制管理

    会发现,bbb账户的金额又变为了1000,说明回滚操作生效了。...,分别代表插入、更新与删除,所以只有这三个关键字才能被事务管理,其它语句是不能被事务管理的。...会发现,aaa用户的账户余额少了100,而bbb用户的余额并没有被改变,显然这种事情是不能被发生在现实生活中的银行业务中的。在这种情况下,为了保证两条sql语句的一致性,我们需要使用事务管理。...再来了解一些高级的事务操作,我们假设,当事务特别复杂的时候,有些情况不会回滚到事务的最开始状态,这时候就需要将事务回滚到指定位置,此时就需要知道 事务回滚点(SavePoint)。...会发现,当前只有4000条数据了,因为程序出现异常,事务记录了第4000条记录的回滚点,并在出现异常之后回滚到了第4000条数据,至此,我们的目的也就实现了。

    1.2K10

    undo日志insert,update,delete (1)—mysql进阶(六十四)

    Redo日志 (5)—mysql进阶(六十三) 事务回滚需求 我们说过事务需要保证原子性, 那么全部完成,要么什么也不做。...事务id怎么生成的 这个事务id本质就是一个数字,他的分配策略和我们前面说的row_id大致相同: 服务器会维护一个全局变量是事务id,当每次需要分配事务id的时候,该变量就+1....我们现在向undo_demo表插入两条记录: BEGIN; # 显式开启一个事务,假设该事务的id为100 # 插入两条记录 INSERT INTO undo_demo(id, key1, col)...BEGIN; # 显式开启一个事务,假设该事务的id为100 # 插入两条记录 INSERT INTO undo_demo(id, key1, col) VALUES (1, 'AWM', '...例子: BEGIN; # 显式开启一个事务,假设该事务的id为100 # 插入两条记录 INSERT INTO undo_demo(id, key1, col) VALUES (1, 'AWM

    45310

    结合图文一起搞懂MySQL事务、MVCC、ReadView!

    ; //事务回滚COMMIT; //事务提交也就是说在你执行了这个命令后,MySQL会将接下来的所有语句视为事务的一部分,直到你提交或者回滚事务。...、delete语句,事务的开启、提交或回滚由mysql内部自动控制的,事务自动开启、提交或回滚。...50的记录也是一条记录,此时事务A插入一条point=150的记录,并提交事务,此时事务B再次查询point>50的记录,同样的条件,出现了两条记录。...Undo日志undo log是为回滚而用,用于记录数据修改前的信息,需要注意的一点是,由于查询操作(SELECT)并不会修改任何用户记录,因此不需要记录相应的undo log。...不同事务或者相同事务的对同一记录的修改,会导致该记录的undo log成为一条记录版本线性表,即版本链表因为undo log 记录事务修改之前版本的数据信息,因此假如由于系统错误或者rollback操作而回滚的话可以根据

    3.6K104

    MySQL:事务知识点盘点

    data file 的已成功事务更新的数据,保证了持久性; Undo log:用来记录数据更新前的值,保证数据更新失败能够回滚,保证了原子性。...假如数据库在执行的过程中,不小心崩了,可以通过该日志的方式,回滚之前已经执行成功的操作,实现事务的一致性: 假如某个时刻数据库崩溃,在崩溃之前有事务A和事务B在执行,事务A已经提交,而事务B还未提交。...假设事务 A 对某些行的内容作了更改,但是还未提交,此时事务 B 插入了与事务 A 更改前的记录相同的记录行,并且在事务 A 提交之前先提交了,而这时,在事务 A 中查询,会发现好像刚刚的更改对于某些数据未起作用...假设现在表中有两条记录,并且 age 字段已经添加了索引,两条记录 age 的值分别为 10 和 30。 此时,在数据库中会为索引维护一套B+树,用来快速定位行记录。...不仅插入 age = 10 的记录需要等待事务A提交,age的记录页无法完成,而大于等于 30 的记录则不受影响,这足以解决幻读问题了。

    32620
    领券