ACID规则简单理解

关系型数据库遵循ACID规则

TRANSACTION(事务)

事务在英文中是transaction,和现实世界中的交易很类似,它有如下四个特性:

1、A (Atomicity) 原子性

原子性很容易理解,也就是说事务里的所有操作要么全部做完,要么都不做,事务成功的条件是事务里的所有操作都成功,只要有一个操作失败,整个事务就失败,需要回滚。

比如银行转账,从A账户转100元至B账户,分为两个步骤:1)从A账户取100元;2)存入100元至B账户。这两步要么一起完成,要么一起不完成,如果只完成第一步,第二步失败,钱会莫名其妙少了100元。

2、C (Consistency) 一致性

一致性也比较容易理解,也就是说数据库要一直处于一致的状态,事务的运行不会改变数据库原本的一致性约束。

例如现有完整性约束a+b=10,如果一个事务改变了a,那么必须得改变b,使得事务结束后依然满足a+b=10,否则事务失败。

3、I (Isolation) 独立性

所谓的独立性是指并发的事务之间不会互相影响,如果一个事务要访问的数据正在被另外一个事务修改,只要另外一个事务未提交,它所访问的数据就不受未提交事务的影响。

比如现在有个交易是从A账户转100元至B账户,在这个交易还未完成的情况下,如果此时B查询自己的账户,是看不到新增加的100元的。

4、D (Durability) 持久性

持久性是指一旦事务提交后,它所做的修改将会永久的保存在数据库上,即使出现宕机也不会丢失。

RDBMS隔离级别设置

数据库
set [session | global ] transaction_isolation level 设置事务隔离级别
select @@transaction_isolation 查询当前事务隔离级别

mysql8 以上更改了原来的事务隔离级别字段 以前老版本是 tx_isolation

如果你的版本比较老 就可以改成 tx_isolation 执行就可以了。

设置 描述
Serializable 可避免脏读、不可重复读、虚读情况的发生。(串行化)
Repeatable read 可避免脏读、不可重复读情况的发生。(可重复读)
Read committed 可避免脏读情况发生(读已提交)。
Read uncommitted 最低级别,以上情况均无法保证。(读未提交)

三种不考虑隔离出现的问题:

  • 1.脏读

    脏读的意思就是在你进行一个事务的同时,读取到了另一个事务未提交的数据

    Example:

    好比别人在银行转账,错转了一笔1个亿的金额到你的账户里面,最后收回去了:

    模拟一下sql:

    update account set money = money + 1000000000 where name = ‘yourname’;

    update account set money = money - 1000000000 where name = ‘others’;

    这两条sql是一个事务,此时别人操作完成 但是并没有提交事务(并没有确定)。


    而你恰好这个时候去查了一下你的账户余额:

    select money from accout where name = ‘yourname’;

    这是一个同时的事务,发现你的账户多出了100000000这么多钱 你很开心,奔走相告,炒了老板鱿鱼,

    然后,别人账户发现转错了,开始了回滚,rollback。

    然后你的钱就没有了。 等过两天你再去查的时候发现钱没了,你很伤心,哭着打电话给老板求他让你回去上班。

  • 2.不可重复读

    不可重复读是指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了。

    例如事务1在读取某一数据,而事务2突然修改了这个数据并且把事务提交了,事务1这时需要再次读取该数据,然后得到了不同的结果,这就是不可重复读。

    不可重复读和脏读的区别是,脏读是某一事务读取了另一个事务未提交的脏数据,而不可重复读则是读取了前一事务提交的数据。

    这里主要是指“update”数据,导致前后读取的数据不一致。 跟幻读需要区分开(后面解释幻读)

    Example:

    你和小明有一个数据库,专门用来记录你俩一起吃饭的日子。

    某一天你们同时想知道上个星期你们什么时候一起吃的饭,然后先后去查了数据库:

    你先查:

    事务1 part1:

    select day_of_week from date_time where time = ‘20200427’;

    你获得的结果是"Wednesday" 此时事务还未结束 小明还要查。


    事务2:

    然后此时柯南中的小黑悄悄登录了你们的数据库,修改了这条记录,改成了"Monday";

    update date_time set day_of_week = ‘Monday’ where time = ‘20200427’;

    commit

    并且提交了该事务,动作十分迅速,只用了零点几秒。


    事务1 part2:

    然后小明的查询语句才开始作用:

    select day_of_week from date_time where time = ‘20200427’;

    他得到的结果就是"Monday" 然后他说你查的不对,你又说他查的不对。 然后你们俩互相指责对方根本不在乎对方,扭打在一起,最后不欢而散,形同陌路,好可惜。

  • 3.幻读

    所谓幻读,指的是当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行。

    但是在可重复读的隔离级别上,会产生幻读的问题。

    Example:

    小明和他老婆相敬如宾,十分恩爱。

    这天小明想给自己的老婆买一个好看的包包,是CHANEL的,买之前,他特意查了下自己老婆的存储宝宝信息的数据库:

    事务1 part1:

    select count(*) from bag_infor where bag_name = ‘channel’;

    结果是0,虽然老婆有20个包包了,但他知道自己从来没有给老婆买过chanel的包包,很惭愧,于是他马上就下单购买。


    事务2:

    小明老婆在外面有情人,叫隔壁老王,隔壁老王也几乎同时给小明老婆买了个chanel的包包,于是:

    insert into bag_info(bag_id, bag_name, worth) values(21, “channel”, “1000000”);

    commit;

    小明老婆就有了第一个包包。 她也很开心,想到小明从来没给自己买过 她觉得心里很不是滋味


    事务1 part2:

    然后小明买的包包也到了,就往里面插入自己买的包包:

    insert into bag_info(bag_id, bag_name, worth) values(21, “channel”, “10000”);

    然后就报错了,主键重复,插入失败!

    select count(*) from bag_infor where bag_name = ‘channel’;

    他又查询,结果发现还是没有记录呀。

    小明百思不得其解 自己买的包包还没有插入啊 咋会突然里面有了一个chanel包包呢。

    小明一直被蒙在鼓里 好惨

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值