小谈事务

1.事务是什么?

并发控制单位,该工作单元内的操作是不可分割的。

2.为什么要使用事务?

高并发环境下,没有一定限制地并发对数据进行操作是不安全的,使用事务可以从某种程度上保障这种“安全”。

3.事务的特性

原子性(Atomicity) :

事务是数据库的逻辑工作单位,事务中包含的各操作要么都做,要么都不做 。

隔离性(Isolation) :

一个事务的执行不能其它事务干扰。一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务之间不能互相干扰,隔离是有程度的,不同的隔离级别也修饰了不同的一致性。

持续性(Durability) :

持续性也称永久性,是指一个事务一旦提交,它对数据库中的数据的改变就应该是永久性的。接下来的其它操作或故障不应该对其执行结果有任何影响。

一致性(Consistency) :

事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。该状态由原子性、持久性保证、由锁操作支持,由隔离性修饰。

解释:

1.当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态。假如数据库系统运行中发生故障,有些事务尚未完成就被迫中断,这些未完成事务对数据库所做的修改有一部分已写入物理数据库,这时数据库就处于一种不一致的状态。那么这个部分显然是由原子性隔离性保证的,保证了物理上的一致性。

2.所有的事务本质也是一段执行逻辑,不同的逻辑对应的也是不同的一致性要求,同时也会有不同的问题。这个部分为了避免问题,就需要通过设置不同的隔离级别,去修饰一致性。而这个部分一般是由数据库的锁机制实现的,这部分保证的是事务的逻辑一致性。

4.事务并发问题

1.脏读

2.不可重复读

3.幻读

4.第一类丢失更新(回滚丢失)

5.第二类丢失更新(修改丢失)

Mysql的数据库默认隔离级别为Committed Read,不能避免不可重复读和第二类丢失更新的问题。要解决这个问题需要采用悲观锁、乐观锁避免

5.第二类丢失更新解决方案

悲观锁

(推荐)在修改数据时先查询下,当然这个查询必须也要加锁(select ...for update nowait),在这里不加for update就不能保证你在查询到更新提交这段时间里这条记录没有被其他会话更新过,所以这种方式也需要在查询时锁定记录,保证在这条记录没有变化的基础上再做更新,若有变化则提示告知用户。

乐观锁

a.旧值法:

就是在sql更新时使用旧的状态值做条件,SQL大致如下 Update table set col1 = newcol1value, col2 = newcol2value…. where col1 = oldcol1value and col2 = oldcol2value….,如果这条记录已经被其他会话更新过,则本次更新了0行,这里我们应用系统一般会做个提示告知用户重新查询更新。这个取哪些旧值作为条件更新视具体系统实际情况而定。(这种方式有可能发生阻塞,如果应用其他地方使用悲观锁法长时间锁定了这条记录,则本次会话就需要等待,所以使用这种方式时最好统一使用乐观锁法。)

b.版本列法:

(推荐)其实这种方式是一个特殊化的前镜像法,就是不需要使用多个旧值做条件,只需要在表上加一个版本列,这一列可以是NUMBER或 DATE/TIMESTAMP列,加这列的作用就是用来记录这条数据的版本(在表设计时一般我们都会给每个表增加一些NUMBER型和DATE型的冗余字段,以便扩展使用,这些冗余字段完全可以作为版本列用),在应用程序中我们每次操作对版本列做维护即可。在更新时我们把上次版本作为条件进行更新。

posted @ 2018-09-03 11:19  CRUD_boys  阅读(268)  评论(0编辑  收藏  举报