mysql+Spring数据库隔离级别与性能分析
这里以mysql为例,先明确以下几个问题: 一.一般项目如果不自己配置事务的话,一般默认的是autocommit,即执行完一个操作后自动commit,提交事务。 (注:事务是绑定在数据库操作上的,也就是当程序执行(statement.excute等操作)转而到数据库层面上的时候,事务才开始发生) 复制代码 代码如下: <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配置事务都是以上的配法,具体参数的意思有不懂的上网自己查吧,那么需要注意以下几点:(题外话) 二.数据库隔离级别 数据库隔离级别主要有以下四个:不可提交读,提交读,重复读和序列化读(以下理解可以不看)。 注意:其中未提交读与序列化读不常用,未提交读危险性太高,会读到很多脏数据。而可串行化读是通过将读取的每一行数据加锁,以耗费性能为代价换取的,所以使用也很少,大部分数据库的隔离级别是提交读,比如oracle、sqlserver。而mysql默认的数据隔离级别是可重复读。 下面我来结合项目分析以下调整数据库隔离级别对性能的影响: 场景:未用Spring,用户A在一个事务中对数据库发出两次查询请求,在两次查询之间,用户B对数据库的记录进行修改。 结果:ISOLATION_REPEATABLE_READ级别:用户A两次查询结果不一样。 ISOLATION_READ_COMMITTED级别:用户A两次查询结果一样,因为对记录进行了加锁操作。
但是如果查询过程中,不涉及同一事务中多次对数据库操作的复杂逻辑及同一事务中多次查询同一结果集的逻辑,则对速度的提升效果并不明显,即事务进行时对数据集加锁的时间是可以忽略的,下面再来理解一下事务隔离级别与锁的关系。 谈到数据库隔离级别,就要说一下锁的概念: 主要分为共享锁和排他锁。 共享锁:由读表操作加上的锁,加锁后其他用户只能获取该表或行的共享锁,不能获取排它锁,也就是说只能读不能写 排它锁:由写表操作加上的锁,加锁后其他用户不能获取该表或行的任何锁,典型是mysql事务中。 个人理解:共享锁和排他锁没有严格的界限,我认为应该通过结果确定加的是共享锁还是排他锁。 例如:用户A修改一条数据,用户B也修改这条数据,挂起。 但是B查看这个数据可以,证明A用户添加了行级共享锁。 再例如:用户A修改一条数据,用户B查询这条数据失败,查询其他数据也失败。那么肯定A加了表级排他锁。 再例如:用户A修改一条数据,用户B查询记录可以,但是修改这条记录不行,修改其他记录也不行,那么A加了表级共享锁。 不同的数据隔离级别,加的锁是不一样的。 回到前面的问题,readonly属性一旦被设置后,数据库级别如果为提交读,那么同一个事务中,如果对两次结果集进行查询,中间间隔修改数据库,那么应该会是同一个结果集,相当于查询的时候采用的是重复读的隔离级别。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |