解决数据库高并发数据脏读问题-全面理解数据库事务ACID特点

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39591494/article/details/89702359

什么是事务


  MySQL事务只要勇于处理操作量大,复杂度高的数据。 比如:在管理系统中删除一个人员的基本资料,也要删除人员的相关信息,文件,邮箱等等,这些数据库的操作语句就构成了一个事务。一个事务是一个只包含所有读/写操作成功的集合。叫做事务
在这里插入图片描述
一个事务的本质上有四个特点:ACID,当然ACID为简称如下:

  • A:Atomicity原子性
  • C:Consistency一致性
  • I : Isolation隔离性
  • D:Durability耐久性
原子性(Atomicity):

  原子性任务是一个独立的操作单元,是一种要么全部都是,要么全部都不是的院子单位性操作,啥意思? 就是 事务要么发生,要么就不发生。

有两个用户:zhangsan和lisi,在zhangsan账户中有1000元的人民币,lisi账户中有200元的人民币,当zhangsan用户给lisi用户转账100元人名币,相当于 zhangsan 1000-100=900 lisi 200+100=300, 原子性表示,要么这两个步骤同时成功,zhangsan转账lisi zhangsan减钱,lisi增钱,要么一起失败。 不然只发生其中一个动作。

一致性(Consistency):

在事务开始之前和事务结束之后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,在zhangsan账户中有1000元的人民币 ,lisi账户中有200元的人民币 当zhangsan用户给lisi用户转账100元人名币,相当于 zhangsan 1000-100=900 lisi 200+100=300,转账成功,一致性表示事务完成后,符合逻辑运算,肯定不能zhangsan向lisi转钱了,zhangsan减钱,lisi没增钱…

隔离性(Isolation):

数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时,由于交叉执行而导致数据的不一致。 事务隔离分为不同的级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。针对多个用户同时操作,主要是排除其他事务对本次事务的影响。
在这里插入图片描述

事务隔离级别 脏读 不可重复读 幻读
读未提交(read-uncommitted)
不可重复读(read-committed)
可重复读(repeatable-read)
串行化(serializable)

在mysql中默认的事务级别为repeatable-read(可重复读)
在这里插入图片描述

读未提交(read-uncommitted):

打开一个客户端将mysql默认REPEATABLE-READ改为:read-uncommitted

select @@tx_isolation; # 查看当前的事务级别
set session transaction isolation level read uncommitted; # 设置事务级别为read uncommitted
start transaction; # -- 整个存储过程指定为一个事务   
select * from accout; # 查看表数据
select @@tx_isolation; # 查看当前事务级别

在这里插入图片描述在这里插入图片描述在这里插入图片描述在以上例子中有一个accout表,数据为id price价格 包括name名字
在这里插入图片描述打开两个终端连接mysql, 分为A和B, 在客户端A的事务提交之前,打开另外一个终端B,对表进行更新;

A的操作:
在这里插入图片描述B的操作
将id=1 的行数据,price = price - 20 也就是zhangsan的price - 20 = 80

set session transaction isolation level read uncommitted;
start transaction;
update accout set price = price - 20 where id = 1
select * from accout;

在这里插入图片描述A的操作:
当B更新了表数据时,此时A是可以看到B更新后的数据的如下:
在这里插入图片描述!!! 当B一旦因为某种原因进行了回滚操作,那么B的所有操作都会撤销,那么id = 1 name=zangsan 的price数据将回滚到100,A读取到的是80,那么A查询到的就是脏数据:

当A和B同时运行:
在这里插入图片描述没有回滚前:
在这里插入图片描述B回滚后
在这里插入图片描述

读已提交(read-committed):

和上面一样,打开两个终端A和B,将事务的模式改为:read-committed
在这里插入图片描述设置事务非自动提交:
在这里插入图片描述值0和OFF都是一样的,当然,1也就表示ON。通过以上设置autocommit=0,则用户将一直处于某个事务中,直到执行一条commit提交或rollback语句才会结束当前事务重新开始一个新的事务。

配置完成之后开始A操作:
在这里插入图片描述在执行A事务未提交时此时通过B终端对此表进行改进操作:
在这里插入图片描述此时通过B终端对数据库表进行了操作,但是事务还没有提交,这个时候通过A读取数据,是读不到B此时修改的数据的。如下:
在这里插入图片描述当B终端commit提交后,如下:
在这里插入图片描述A终端查看数据:
在这里插入图片描述那么此时已经解决了并发时脏读的问题

可重复读(repeatable-read)

mysql默认为:repeatable-read模式,所以就不需要set session 设置模式了。
在A未提交事务时同时操作B
在这里插入图片描述B操作:
在这里插入图片描述A操作查看数据,并没有读到B操作的数据。
在这里插入图片描述此时B进行commit操作

-- set autocommit = 0

-- update accout set price = price - 10 where id = 1;
commit;
select * from accout;

查看A:
数据没有发生变化
在这里插入图片描述目前A没有提交事务,当A执行update accout set price = price - 10 where id = 1; 结果如下:
在这里插入图片描述在客户端A,执行操作update accout set price = price - 10 where id = 1;时候按道理来说应该是100-10=90 但是最后commit提交事务之后数据变成了80, 80是由B终端减去的数据得来的 B操作=100-10=90 commit提交,A终端不显示B提交的结果数据,当A进行操作并提交时,数据还是可以保持一致性,数据的一致性倒是没有被破坏。可重复读的隔离级别下使用了MVCC机制,select操作不会更新版本号,是快照读(历史版本);insert、update和delete会更新版本号,是当前读(当前版本)。如下B:
保持了数据的一致性:
在这里插入图片描述


按照MySQL默认的事务模式来测试,例如,开两个终端A和B 当A进行操作时,此时A并未提交数据,这个时候当B做了操作,不会影响A操作数据的过程,当A事务提交后数据将统一,如下:
A进行操作,当A事务没有提交时B新增一条数据如下:(A)
在这里插入图片描述B插入一条数据:
在这里插入图片描述A查看表数据
并没有任何变化。
在这里插入图片描述当B提交事务:(在从A端查看)
在这里插入图片描述在这里插入图片描述当A-commit事务提交,数据将保持一致
在这里插入图片描述

串行化(serializable)

打开一个客户端A,并设置当前事务模式为serializable,查询表account的初始值:
在这里插入图片描述
打开一个客户端B,并设置当前事务模式为serializable,插入一条记录报错,表被锁了插入失败,mysql中事务隔离级别为serializable时会锁表,因此不会出现幻读的情况,这种隔离级别并发性极低,开发中很少会用到。
在这里插入图片描述以上描述了ACID隔离性不同的级别


持久性(Durability):

事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

在写本篇文章前我共参考了如下文章:
https://blog.csdn.net/gaojingyuan/article/details/78983918
https://jingyan.baidu.com/article/066074d6f835ebc3c21cb0ea.html
https://blog.csdn.net/mergades/article/details/51009650
https://www.cnblogs.com/coolhtm/p/4411036.html
https://www.cnblogs.com/kerrycode/p/8649101.html
https://bbs.csdn.net/topics/390585631
https://www.cnblogs.com/huanongying/p/7021555.html
https://www.runoob.com/mysql/mysql-transaction.html
https://blog.csdn.net/dengjili/article/details/82468576
https://www.jdon.com/concurrent/acid-database.html
http://blog.itpub.net/30126024/viewspace-2216435/

本文为个人学习总结,同时希望对您有所帮助,祝大家51快乐~~~
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_39591494/article/details/89702359
今日推荐