美文网首页
数据库事务—并发—隔离级别(并发与锁)

数据库事务—并发—隔离级别(并发与锁)

作者: 兮兮码字的地方 | 来源:发表于2019-03-07 19:00 被阅读2次

    一,事务

    事务是访问数据库的一个操作序列,数据库应用系统通过事务集来完成对数据库的存取。

    事务必须服从ACID原则。ACID是原子性(atomicity)、一致性(consistency)、隔离性(isolation)、持久性(durability)的缩写,这四种状态的意思是:

    1、原子性

    即不可分割,事务要么所有子事务全部被执行,要么全部不执行。

    2、一致性

    事务的执行使得数据库从一种正确状态转换成另外一种正确状态。

    3、隔离性

    在事务正确提交之前,不允许把事务对该数据的改变提供给任何其他事务,即在事务正确提交之前,它可能的结果不应该显示给其他事务。

    4、持久性

    事务正确提交之后,其结果将永远保存在数据库之中。

    事务的作用

    事务管理保证了用户的每一次操作都是可靠的,即便出现了异常的访问情况或各种故障,也不至于破坏后台数据的完整性。

    二,并发下事务可能产生的问题

    当多个事务操纵的是同一个资源,事务有若干个子事务,在高并发的情况下,会出现各种各样的问题。"

    主要有五种:第一类丢失更新、第二类丢失更新、脏读、不可重复读、幻读。

    1.脏读

    所谓脏读,就是指事务A读到了事务B还没有提交的数据。

    2、不可重复读

    所谓不可重复读,就是指在同一个事务里面读取了两次某个数据,读出来的数据不一致。

    3、幻读

    所谓幻读,就是指在同一个事务里面的操作(如commit)中发现了未被操作的数据。幻读出现的前提是并发的事务中有事务发生了插入、删除操作。

    三,事务隔离级别

    事务隔离级别,就是为了解决上面几种问题而诞生的。为什么要有事务隔离级别,因为事务隔离级别越高,在并发下会产生的问题就越少,但同时付出的性能消耗也将越大,因此很多时候必须在并发性和性能之间做一个权衡。

    每种关系型数据库都提供了各自特色的隔离级别实现,都是以锁为实现单元,只不过实际的实现不同。

    1.MySQL 事务隔离级别分为四个不同层次:

    读未提交(Read uncommitted),就是一个事务能够看到其他事务尚未提交的修改,这是最低的隔离水平,允许脏读出现。

    读已提交(Read committed),事务能够看到的数据都是其他事务已经提交的修改,也就是保证不会看到任何中间性状态,当然脏读也不会出现。读已提交仍然是比较低级别的隔离,并不保证再次读取时能够获取同样的数据,也就是允许其他事务并发修改数据,允许不可重复读和幻象读(Phantom Read)出现。

    可重复读(Repeatable reads),保证同一个事务中多次读取的数据是一致的,这是 MySQL InnoDB 引擎的默认隔离级别,但是和一些其他数据库实现不同的是,可以简单认为 MySQL 在可重复读级别不会出现幻读

    串行化(Serializable),并发事务之间是串行化的,通常意味着读取需要获取共享读锁,更新需要获取排他写锁,如果 SQL 使用 WHERE 语句,还会获取区间锁(MySQL 以 GAP 锁形式实现,可重复读级别中默认也会使用),这是最高的隔离级别。

    2.Spring的5种事务隔离级别

    DEFAULT

    默认隔离级别,每种数据库支持的事务隔离级别不一样,如果Spring配置事务时将isolation设置为这个值的话,那么将使用底层数据库的默认事务隔离级别。如果使用的MySQL,可以使用"select @@tx_isolation"来查看默认的事务隔离级别

    READ_UNCOMMITTED

    读未提交,即能够读取到没有被提交的数据,所以很明显这个级别的隔离机制无法解决脏读、不可重复读、幻读中的任何一种,因此很少使用。

    READ_COMMITED

    读已提交,即能够读到那些已经提交的数据,自然能够防止脏读,但是无法限制不可重复读和幻读

    REPEATABLE_READ

    重复读取,即在数据读出来之后加锁,类似"select * from XXX for update",明确数据读取出来就是为了更新用的,所以要加一把锁,防止别人修改它。REPEATABLE_READ的意思也类似,读取了一条数据,这个事务不结束,别的事务就不可以改这条记录,这样就解决了脏读、不可重复读的问题,但是幻读的问题还是无法解决

    SERLALIZABLE

    串行化,最高的事务隔离级别,不管多少事务,挨个运行完一个事务的所有子事务之后才可以执行另外一个事务里面的所有子事务,这样就解决了脏读、不可重复读和幻读的问题了

    数据库事务—并发—隔离级别(并发与锁)

    四,悲观锁和乐观锁

    锁并不是 MySQL 或者数据库中独有的概念,而是并发编程的基本概念。主要区别在于,操作共享数据时,“悲观锁”即认为数据出现冲突的可能性更大,而“乐观锁”则是认为大部分情况不会出现冲突,进而决定是否采取排他性措施。

    MySQL 中,悲观锁一般就是利用类似 SELECT … FOR UPDATE 这样的语句,对数据加锁,避免其他事务意外修改数据。乐观锁则是利用 CAS 机制,并不会对数据加锁,而是通过对比数据的时间戳或者版本号,来实现乐观锁需要的版本判断。

    五,java访问数据库

    目前最为通用的 Java 和数据库交互技术就是 JDBC,最常见的开源框架基本都是构建在 JDBC 之上,包括我们熟悉的JPA/Hibernate、MyBatis、Spring JDBC Template 等,各自都有独特的设计特点。

    Hibernate 是典型的 O/R Mapping 框架之一,它是以对象为中心的,其可以很方便地在 Java 对象层面体现外键约束等相对复杂的关系。内部大量使用了懒加载等技术提高效率。并且,为了屏蔽数据库的差异,降低维护开销,Hibernate 提供了类 SQL 的 HQL,可以自动生成某种数据库特定的 SQL 语句。

    Hibernate 过度强调持久化和隔离数据库底层细节,也导致了很多弊端,例如 HQL 需要额外的学习,未必比深入学习 SQL 语言更高效;减弱程序员对 SQL 的直接控制,还可能导致其他代价,本来一句 SQL ,可能被 Hibernate 生成几条,隐藏的内部细节也阻碍了进一步的优化。

    而 MyBatis 虽然提供了一些映射的功能,但更加以 SQL 为中心,开发者可以侧重于 SQL 和存储过程,非常简单、直接。如果我们的应用需要大量高性能的或者复杂的 SELECT 语句等,“半自动”的 MyBatis 就会比 Hibernate 更加实用。

    而 Spring JDBC Template 也是更加接近于 SQL 层面,Spring 本身也可以集成 Hibernate 等 O/R Mapping 框架。


    学习主流框架的架构和设计理念的重点:

    1.SQL 解析生成、SQL 执行到结果映射等处理过程的理解。

    2.映射等部分的细节定义和原理。

    更多mysql事务的讲解资料

    mysql事务

    https://baijiahao.baidu.com/s?id=1572543485267773&wfr=spider&for=pc&isFailFlag=1

    相关文章

      网友评论

          本文标题:数据库事务—并发—隔离级别(并发与锁)

          本文链接:https://www.haomeiwen.com/subject/ytyhpqtx.html