数据库事务详解

什么是『事务』?

事务就是一组具有原子性的操作,这一组操作要么全都正确执行,要么全都不执行。 事务能保证数据库从一种一致性状态转换为另一种一致性状态。

事务的四大特性ACID

1. 原子性

原子性指的是事务是一个不可分割的操作,要么全都正确执行,要么全都不执行。

2. 一致性

事务开始前和事务结束后,数据库的完整性约束没有被破坏。

3. 隔离性

事务的执行是相互独立的,它们不会相互干扰,一个事务不会看到另一个正在运行过程中的事务的数据。

4. 持久性

事务结束后,事务的结果必须是永久保存的。即使数据库发生崩溃,在数据库恢复后事务提交的结果仍然不会丢失。 PS:事务只能保证数据库的高可靠性,即数据库本身发生问题后,事务提交后的数据仍然能恢复;而如果不是数据库本身的故障,如硬盘损坏了,那么事务提交的数据可能就丢失了。这属于『高可用性』的范畴。因此,事务只能保证数据库的『高可靠性』,而『高可用性』需要整个系统共同配合实现。

事务的分类

1. 扁平事务

  • 它是实际生产环境中最常用、最简单的事务类型。
  • 事务从BEGIN WORK开始,从COMMIT WORK或ROLLBACK WORK结束。
  • 缺点:发生错误时回滚到事务的起始位置,无法回滚部分操作。而回滚所有的操作开销太大。

2. 带有保存点的扁平事务

这种事务能设置多个保存点,当发生错误时可以回滚到事务中指定的保存点,而不需要将整个事务回滚。

3. 链事务

4. 嵌套事务

5. 分布式事务

数据库并发访问会出现的问题

1. 更新丢失

当有两个并发执行的事务,更新同一行数据,那么有可能一个事务会把另一个事务的更新覆盖掉。 当数据库没有加任何锁操作的情况下会发生。

2. 脏读

一个事务读到另一个尚未提交的事务中的数据。 该数据可能会被回滚从而失效。 如果第一个事务拿着失效的数据去处理那就发生错误了。

3. 不可重复读

不可重复度的含义:一个事务对同一行数据读了两次,却得到了不同的结果。它具体分为如下两种情况: 1. 虚读:在事务1两次读取同一记录的过程中,事务2对该记录进行了修改,从而事务1第二次读到了不一样的记录。 2. 幻读:事务1在两次查询的过程中,事务2对该表进行了插入、删除操作,从而事务1第二次查询的结果发生了变化。

与『脏读』的区别? 脏读读到的是尚未提交的数据,而不可重复读读到的是已经提交的数据,只不过在两次读的过程中数据被另一个事务改过了。

事务的隔离级别

数据库事务的隔离级别有4个,由低到高依次为Read uncommitted 、Read committed 、Repeatable read 、Serializable ,这四个级别可以逐个解决脏读 、不可重复读 、幻读 这几类问题。

1. Read uncommitted 读未提交

在该级别下,一个事务对一行数据修改的过程中,不允许另一个事务对该行数据进行修改,但允许另一个事务对该行数据读。 因此本级别下,不会出现更新丢失,但会出现脏读、不可重复读。

2. Read committed 读提交

在该级别下,未提交的写事务不允许其他事务访问该行,因此不会出现脏读;但是读取数据的事务允许其他事务的访问该行数据,因此会出现不可重复读的情况。

3. Repeatable read 重复读

在该级别下,读事务禁止写事务,但允许读事务,因此不会出现同一事务两次读到不同的数据的情况(不可重复读),且写事务禁止其他一切事务。

4. Serializable 序列化

该级别要求所有事务都必须串行执行,因此能避免一切因并发引起的问题,但效率很低。

隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。对于多数应用程序,可以优先考虑把数据库系统的隔离级别设为Read Committed。它能够避免脏读取,而且具有较好的并发性能。尽管它会导致不可重复读、幻读和第二类丢失更新这些并发问题,在可能出现这类问题的个别场合,可以由应用程序采用悲观锁或乐观锁来控制。

使用事务的注意事项

1. 不要在循环中提交事务

2. 不要使用自动提交

3. 不要使用自动回滚

4. 不要使用长事务

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏杨建荣的学习笔记

和Null有关的函数(r3笔记第48天)

关于null相关的函数在日常的工作中还有比较实用的,可能会碰到各种和Null校验相关的情况,大体有以下几种。 case when decode nvl nvl...

30012
来自专栏阿杜的世界

【转】Innodb中的事务隔离级别和锁的关系一次封锁or两段锁?事务中的加锁方式参考资料

因为有大量的并发访问,为了预防死锁,一般应用中推荐使用一次封锁法,就是在方法的开始阶段,已经预先知道会用到哪些数据,然后全部锁住,在方法运行之后,再全部解锁。这...

633
来自专栏芋道源码1024

数据库中间件 Sharding-JDBC 源码分析 —— JDBC实现与读写分离

本文主要基于 Sharding-JDBC 1.5.0 正式版 1. 概述 2. unspported 包 3. adapter 包 3.1 WrapperAda...

3358
来自专栏数据和云

深入剖析-关于分页语句的性能优化

分页语句是数据库开发和应用场景比较常见的需求,即按照特定的where条件进行过滤,然后在按照一个或者多个条件进行排序(如果不进行排序无法确执行时候无法返回相同的...

2659
来自专栏xiaoheike

Hibernate save, saveOrUpdate, persist, merge, update 区别

hibernate save()方法能够保存实体到数据库,正如方法名称save这个单词所表明的意思。我们能够在事务之外调用这个方法,这也是我不喜欢使用这个方法保...

713
来自专栏微信公众号:Java团长

深入理解Mysql——锁、事务与并发控制

本文对锁、事务、并发控制做一个总结,看了网上很多文章,描述非常不准确。如有与您观点不一致,欢迎有理有据的拍砖!

713
来自专栏知识分享

JDBC基本知识

JDBC的作用 JDBC为java访问数据库提供通用的API,可以为多种关系数据库提供统一访问。因为SQL是关系式数据库管理系统的标准语言,只要我们遵循SQL规...

33911
来自专栏从流域到海域

SQL连接查询(最全面)

连接查询是关系数据库中最主要的查询,主要包括内连接、外连接和交叉连接等。通过连接运算符可以实现多个表查询。 在关系数据库管理系统中,表建立时各数据之间...

1907
来自专栏Java面试笔试题

JDBC中如何进行事务处理?

Connection提供了事务处理的方法,通过调用setAutoCommit(false)可以设置手动提交事务;当事务完成后用commit()显式提交事务;如果...

532
来自专栏运维咖啡吧

Django model select的各种用法详解

Q对象可以对关键字参数进行封装,从而更好的应用多个查询,可以组合&(and)、|(or)、~(not)操作符。

753

扫描关注云+社区