mysql+Spring数据库隔离级别与性能分析

 更新时间:2014年05月01日 23:57:39   作者:  
数据库隔离级别与Spring配置事务的联系及性能影响,以下是个人理解,如果有瑕疵请及时指正

这里以mysql为例,先明确以下几个问题:

一.一般项目如果不自己配置事务的话,一般默认的是autocommit,即执行完一个操作后自动commit,提交事务。

(注:事务是绑定在数据库操作上的,也就是当程序执行(statement.excute等操作)转而到数据库层面上的时候,事务才开始发生)
当然spring可以将几个数据库操作动作绑在一个事务中,这样就需要介绍下spring事务配置方法,下面介绍的是常用方法,其他方法网上有很多。
spring提供了很多事务配置的策略,很方便,简要介绍一下:

复制代码 代码如下:

 <property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
</props>

一般spring配置事务都是以上的配法,具体参数的意思有不懂的上网自己查吧,那么需要注意以下几点:(题外话)
1.我习惯将事务配置在service上,这时需要注意,只有service中以save、update等开头的方法,配置的事务才有效果。如果service中的方法名不是以save等开头的,比如taskSave()方法,即使在实现类中调用了service中的update方法,配置事务也失效,我试过。
2.readOnly这个属性很有意思,因为用了它后,会自动将数据库的隔离级别提高了一级,由提交读变为重复读,这块我后面说明。

二.数据库隔离级别

数据库隔离级别主要有以下四个:不可提交读,提交读,重复读和序列化读(以下理解可以不看)。
1. ISOLATION_READ_UNCOMMITTED: 这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。
     这种隔离级别会产生脏读,不可重复读和幻像读。
2. ISOLATION_READ_COMMITTED: 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据
3. ISOLATION_REPEATABLE_READ: 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。
     它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
4. ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。
     除了防止脏读,不可重复读外,还避免了幻像读。
mysql默认的隔离级别是重复读,即 ISOLATION_REPEATABLE_READ。

注意:其中未提交读与序列化读不常用,未提交读危险性太高,会读到很多脏数据。而可串行化读是通过将读取的每一行数据加锁,以耗费性能为代价换取的,所以使用也很少,大部分数据库的隔离级别是提交读,比如oracle、sqlserver。而mysql默认的数据隔离级别是可重复读。

下面我来结合项目分析以下调整数据库隔离级别对性能的影响:
本地mysql数据库由ISOLATION_REPEATABLE_READ级别降低到ISOLATION_READ_COMMITTED级别:

场景:未用Spring,用户A在一个事务中对数据库发出两次查询请求,在两次查询之间,用户B对数据库的记录进行修改。

结果:ISOLATION_REPEATABLE_READ级别:用户A两次查询结果不一样。

          ISOLATION_READ_COMMITTED级别:用户A两次查询结果一样,因为对记录进行了加锁操作。


以task模块为例,在本地运行任务首页,通过对比分析两种事务处理方式得到如下结果(每次统计数据前均清理浏览器缓存,统计3次取平均值):


发现降低数据库事务的隔离级别,对于一些特殊逻辑的操作上,性能有所提升。
但是如果查询过程中,不涉及同一事务中多次对数据库操作的复杂逻辑及同一事务中多次查询同一结果集的逻辑,则对速度的提升效果并不明显,即事务进行时对数据集加锁的时间是可以忽略的,下面再来理解一下事务隔离级别与锁的关系。

谈到数据库隔离级别,就要说一下锁的概念:

主要分为共享锁和排他锁。
共享锁:由读表操作加上的锁,加锁后其他用户只能获取该表或行的共享锁,不能获取排它锁,也就是说只能读不能写

排它锁:由写表操作加上的锁,加锁后其他用户不能获取该表或行的任何锁,典型是mysql事务中。

个人理解:共享锁和排他锁没有严格的界限,我认为应该通过结果确定加的是共享锁还是排他锁。

例如:用户A修改一条数据,用户B也修改这条数据,挂起。 但是B查看这个数据可以,证明A用户添加了行级共享锁。

再例如:用户A修改一条数据,用户B查询这条数据失败,查询其他数据也失败。那么肯定A加了表级排他锁。

再例如:用户A修改一条数据,用户B查询记录可以,但是修改这条记录不行,修改其他记录也不行,那么A加了表级共享锁。

不同的数据隔离级别,加的锁是不一样的。

回到前面的问题,readonly属性一旦被设置后,数据库级别如果为提交读,那么同一个事务中,如果对两次结果集进行查询,中间间隔修改数据库,那么应该会是同一个结果集,相当于查询的时候采用的是重复读的隔离级别。

相关文章

  • MySQL RC事务隔离的实现原理

    MySQL RC事务隔离的实现原理

    这篇文章主要介绍了MySQL RC事务隔离的实现,Read Committed,事务运行期间,只要别的事务修改数据并提交,即可读到人家修改的数据,所以会有不可重复读、幻读问题,下文相关介绍需要的朋友可以参考下
    2022-03-03
  • Mysql中xtrabackup备份的实现

    Mysql中xtrabackup备份的实现

    Xtrabackup是Percona团队开发的用于MySQL数据库物理热备份的开源备份工具,本文就来介绍一下Mysql中xtrabackup备份的实现,就有一定的参考价值,感兴趣的可以了解一下
    2023-12-12
  • 关于Mysql的InnoDB锁概述

    关于Mysql的InnoDB锁概述

    这篇文章主要介绍了关于Mysql的InnoDB锁概述,对于更新操作(UPDATE、INSERT、DELETE),InnoDB会自动给涉及到的数据集加排他锁,需要的朋友可以参考下
    2023-05-05
  • MySql8 WITH RECURSIVE递归查询父子集的方法

    MySql8 WITH RECURSIVE递归查询父子集的方法

    这篇文章主要介绍了MySql8 WITH RECURSIVE递归查询父子集的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • MySQL 如何将查询结果导出到文件(select … into Statement)

    MySQL 如何将查询结果导出到文件(select … into Statement)

    我们经常会遇到需要将SQL查询结果导出到文件,以便后续的传输或数据分析的场景,本文就MySQL中select…into的用法进行演示,感兴趣的朋友跟随小编一起看看吧
    2024-08-08
  • mysql insert if not exists防止插入重复记录的方法

    mysql insert if not exists防止插入重复记录的方法

    在 MySQL 中,插入(insert)一条记录很简单,但是一些特殊应用,在插入记录前,需要检查这条记录是否已经存在,只有当记录不存在时才执行插入操作,本文介绍的就是这个问题的解决方案。
    2011-04-04
  • 解决MySQL Varchar 类型尾部空格的问题

    解决MySQL Varchar 类型尾部空格的问题

    这篇文章主要介绍了MySQL Varchar 类型尾部空格,在这里需要注意的是 binary 排序规则的 pad 属性为 NO PAD,这里其实不是个例外,因为 char、varchar 和 text 类型都归类为 nonbinary,感兴趣的朋友跟随小编一起学习下吧
    2022-04-04
  • MySQL事务日志(redo log和undo log)的详细分析

    MySQL事务日志(redo log和undo log)的详细分析

    innodb事务日志包括redo log和undo log,redo log是重做日志,提供前滚操作,undo log是回滚日志,提供回滚操作,下面这篇文章主要给大家介绍了关于MySQL事务日志(redo log和undo log)的详细分析,需要的朋友可以参考下
    2022-04-04
  • MySQL高可用MMM方案安装部署分享

    MySQL高可用MMM方案安装部署分享

    这篇文章主要介绍了MySQL高可用MMM方案安装部署方法,需要的朋友可以参考下
    2014-02-02
  • 解决MySQL去除密码登录告警的问题

    解决MySQL去除密码登录告警的问题

    这篇文章主要介绍了MySQL去除密码登录告警的问题,解决方法是使用mysql_config_editor,本文通过示例代码给大家介绍的非常详细,需要的朋友可以参考下
    2022-04-04

最新评论