数据库事务隔离级别

数据库事务指的是一组数据操作或者说一组SQL操作,事务内的操作要么就是全部成功,要么就是全部失败,如果做了一部分但是只要有一步失败,就要回滚所有操作。

事务的ACID特性

  • 原子性(Atomicity): 一个事务是一个单元工作,当中可能包括数个步骤,这些步骤必须全部执行成功,若有一个失败,则整个事务声明失败,事务中其他步骤必须撤销曾经执行过的动作,回到事务前的状态。MySQL中事务的回滚是通过回滚(Undo log)实现的,回滚日志记录的是你所有操作的逆操作,在需要回滚时,就把回滚日志里的操作全部执行一次。

  • 一致性(Consistency): 事务作用的数据集合在事务前后必须一致,若事务成功,整个数据集合都必须是事务操作后的状态;若事务失败,整个数据集合必须与开始事务前一样没有变更,不能发生整个数据集合部分有变更,部分没变更的状态。

  • 隔离行为(Isolation):在多人使用的环境下,每个用户可能进行自己的事务,事务与事务之间,必须互不干扰,用户不会意识到别的用户正在进行事务,就好像只有自己在进行操作一样。

  • 持续性(Durability):事务一旦成功,所有变更必须保存下来,即使系统故障,事务的结果也不能遗失。这通常需要系统软、硬件架构的支持。

事务隔离级别

SQL标准定义了四种事务隔离级别,MySQL全都支持,分别如下:

  1. 读未提交(READ UNCOMMITTED)

  2. 读提交(READ COMMITTED)

  3. 可重复读(REPEATABLE READ)

  4. 串行化(SERIALIZABLE)

要了解这四个级别的影响,需要先了解多个事务并行时可能引发的数据不一致问题有哪些。

  1. 更新遗失。基本上就是指某个事务对字段进行更新的信息,因另一个事务的介入而遗失更新效力。解决办法就是设置“读未提交”隔离级别,这样事务A已更新但未提交的数据,事务B只能进行读取操作,但不能进行更新操作。

  1. 脏读。两个事务同时进行,其中一个事务更新数据但未提交,另一个事务就读取数据,就有可能发生脏读问题,也就是读到所谓脏数据、不干净、不正确的数据。如事务A更新了字段但未确认,事务B读取了,然后事务A撤回了,那么B读到的就不是提交的数据。要避免脏读,可以设置“读提交”隔离级别,也就是事务读取的数据必须是其他事务已提交的数据,如果存在未提交的更新事务,需要等待。

  2. 无法重复的读取 某个事务两次读取同一字段的数据并不一致。例如事务A在事务B更新前后进行数据的读取,则A事务会得到不同的结果,相当于事务A的两次读期间插入了一个更新字段的事务B。这种情况读提交级别就解决不了,此时需要设置“可重复读”隔离级别,也就是同一事务内两次读取的数据必须相同,这种级别下读取事务不会阻止其他读取事物,但是会阻止其他更新事务。

  3. 幻读 同一事务期间,读取到的数据笔数不一致。例如,事务A第一次读取得到五笔数据,此时事务B新增了一笔数据,导致事务B再次读取得到六笔数据。这种情况可重复读级别就解决不了,需要使用串行化级别,也就是在有事务时若有数据不一致的疑虑,事务必须可以按照顺序逐一进行。串行化情况下事务一个一个循序进行,对数据库的性能影响非常大。

各个事务隔离级别所解决的问题对比情况如下表:

隔离级别

更新遗失

脏读

无法重复的读取

幻读

读未提交

预防

读提交

预防

预防

可重复读

预防

预防

预防

串行化

预防

预防

预防

预防

事务隔离级别越高并发事务就越安全,但是带来的性能开销也就越大,所以要根据系统需求进行选择,MySQL默认的隔离级别是可重复读取级别,Oracle则是读提交级别。

实现上,JDBC定义了五个事务隔离级别

  • TRANSACTION_NONE

  • TRANSACTION_READ_UNCOMMITTED

  • TRANSACTION_READ_COMMITTED

  • TRANSACTION_REPEATABLE_READ

  • TRANSACTION_SERIALIZABLE

其中TRANSACTION_NONE表示对事务不设置隔离行为,仅适用于没有事务、以只读功能为主、不会发生同时修改字段的数据库。有事务功能的数据库,可能不理会TRANSACTION_NONE的设置提示。如果要在JDBC层面使用事务,需要在执行SQL语句前关闭自动提交机制,执行完后手动调用commit()提交。这样中间执行过程中如果有SQL语句执行失败就会触发回滚。

conn.setAutoCommit(false); // default true

// start transaction block



// insert

// update

// if any errors within the start and end block,

// rolled back all changes, none of the statements are executed.



// end transaction block

conn.commit();

MySQL中事务隔离实现参考知乎文章MySQL中是如何实现事务隔离的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值