数据库事务以及隔离级别

1 篇文章 0 订阅

事务

事务的作用是保护数据的原子性,ACID中的A(Atomic)。 它将一些列的操作作为一个原子操作来执行:要不都成功,要不都失败!以此来保证数据的完整性。

在JDBC中,一个连接的默认提交方式是Auto-Commit模式。在这种模式下,每个单独的SQL都会被视为一个事务,当SQL执行时,立刻就会被提交到数据库里面。但如果有业务需求 要将多个操作放在一起的时候,比如用户 用代金券买了一本书,那么需要同时更新代金券的使用状态,以及买书订单的支付状态。这种情况下,代金券的使用状态跟买书订单的支付状态必须要 完整的,要么都更新,要么都rollback。 所以就需要用到Transaction。

事务隔离

使用事务,我们可以保证一系列操作的原子性,但是却不能保证多个事务之间的影响。所以就有可能会出现脏读,不可重复读,和幻读的情况。这时,就需要借助于事务隔离级别来 缓解这种情况。

脏读

脏读是指读取到别人还没commit的内容。比如年底到了,HR Lilei将你的工资从10k/month 改为15K/month,正准备commit呢,这时领导过来跟他说要把你的工资再整高点,弄到18k/month!!! (良心之举啊)。 就在Lilei跟领导沟通时,HR Lily要调整今年的公积金,所以打开系统查看你的工资是多少。假定这时事务隔离级别是TRANSACTION_READ_UNCOMMITTED,那么这时 Lily读到你的工资是15k/month,发现你的工资已经涨了,所以就拿15k/month去调整你的公积金。也就在此刻,Lilei聊完天,把你的工资改为18k/month并且commit了。

这就是脏读,可以通过将隔离级别提高到 TRANSACTION_READ_COMMITTED 来避免这事的发生.

不可重复读

不可重复读是指 在一个事务当中,相同的查询条件,在事务的不同阶段中 返回的查询结果可能不同。比如在你的事务刚开始的时候,你查询年龄大于35岁的码农返回35个,就在这时HR往系统新增一个38岁的码农,这是你再查询年龄大于35岁的码农,就会发现返回36个!

这就是不可重复读,可以通过将隔离级别提高到TRANSACTION_REPEATABLE_READ来避免这事的发生

幻读

幻读是指你以为你以为已经改好所有的记录,但实际有可能不是。你看到的未必是真实的!比如你要去把年龄大于35岁的码农 跳槽系数降 1 ,那么你首先会查出所有年龄大于35岁的码农,然后逐条修改跳槽系数,最后再保存进去。可就在你刚刚查询数据库时,新来一个年龄38岁的码农,这时,如果事务隔别级别为TRANSACTION_REPEATABLE_READ,那么在你的当前操作当中,你是看不到这个新来的码农的。所以当你做完之后,你以为全部大于35岁的码农都修改了,然并无,所以谓之幻读

幻读可以通过将隔离级别提高到TRANSACTION_SEARIABL,但一般不这么做,因为TRANSACTION_SEARIABL将变成串行执行了,对性能有很大影响!

隔离级别

  1. TRANSACTION_NONE
    TRANSACTION_NONE以为着木有事务,所以也就不存在隔离级别

  2. TRANSACTION_READ_UNCOMMITTED
    在这个隔离级别中,有可能会发生脏读,不可重复读以及幻读

  3. TRANSACTION_READ_COMMITTED
    在这个隔离级别中,不会出现脏读,因为用户只能读取到别人已经commit的记录。 但也可能出现不可重复读 和幻读

  4. TRANSACTION_REPEATABLE_READ
    在这个隔离级别中,不会出现脏读 和 不可重复读,但还是会出现幻读。

  5. TRANSACTION_SEARIABL
    这是个终极隔离级别,意味着串行执行各个事务,不会出现各种读问题,但是一般不行,性能大大的下降

实践说明

这4个隔离级别是SQL的标准规范,但其实现是每个数据库产品执行实现,所以并不是每一个数据库产品都完完全全地实现这4种隔离级别.
一般的DBMS默认都会使用 READ_COMMITTED 作为隔离级别,比如Oracle DB, SQLServer, 但是MYSQL的隔离级别为 TRANSACTION_REPEATABLE_READ.

  • MYSQL
    MYSQL的确是完全地实现了这4种隔离级别。而且MYSQL默认的隔离级别就是 TRANSACTION_REPEATABLE_READ.因为是跟binlog有关,可以参考这篇文章MySQL使用可重复读作为默认隔离级别的原因。MYSQL是通过阻塞其它事务的操作来达到 可重复性读 的隔离级别

  • Oracle DB
    OracleDB 默认是READ_COMMITTED. 但是Oracle并没有完全实现4种隔离级别,只实现了 READ_COMMITTED 和 SERRIABLE.

使用场景

待补充!有高人补充更佳!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值