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

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

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

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

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

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

相关·内容

咦,为什么事务不了?

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

97820

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

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

1.1K20
  • 事务控制

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

    15630

    PostgreSQLMVCC vs InnoDBMVCC

    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 事务,让操作对数据页修改生效。

    14210

    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上面加锁,为什么会产生死锁呢? 如果看过上篇文章,就会明白。

    39951

    Spring事物传播行为案例分析

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

    56510

    Spring事务传播行为案例分析

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

    97710

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

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

    25510

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

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

    81910

    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

    42910

    结合图文一起搞懂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操作而回的话可以根据

    3K93

    MySQL:事务知识点盘点

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

    32220

    数据库事务事务隔离级别

    数据库acid特性 Atomicity(原子性) 原子性表示该操作不可再被分割,要么全部成功,要么全部失败。可以用日志来实现,日志记录事务所执行修改操作,在时反向执行这些修改操作即可。...两个并发事务,A事务和B事务同时操作了同一行数据,A将数据修改之后,此条数据被B事务读取,之后如果A将事务B就读到了无效“脏数据”。...(同时操作,事务1分别读取事务2操作时和提交后数据,读取记录内容不一致。不可重复读是指在同一个事务内,两个相同查询返回了不同结果。...) 幻读 事务 T1 读取一条指定 Where 子句所返回结果集,然后 T2 事务插入一行记录,这行记录恰好可以满足T1 所使用查询条件。...但是却没有办法控制幻读,因为这个时候其他事务不能更改所选数据,但是可以增加数据,即前一个事务有读锁但是没有范围锁,为什么叫做可重复读等级呢?那是因为该等级解决了下面的不可重复读问题。

    42020
    领券