失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 数据库事务的四大特性 四种隔离级别 如何避免脏读 不可重复读 幻读(如何加锁)?

数据库事务的四大特性 四种隔离级别 如何避免脏读 不可重复读 幻读(如何加锁)?

时间:2020-01-29 00:24:15

相关推荐

数据库事务的四大特性 四种隔离级别 如何避免脏读 不可重复读 幻读(如何加锁)?

目录

第一章 数据库基础知识


文章目录

目录前言数据库事务一、定义二、要求三、影响四、特性(ACID)(1)A:原子性 Atomicity(2)C:一致性 Consistency(3)I:隔离性 Isolation事务的隔离级别及解决方案1.未提交读2.已提交读3.可重复读4.可串行化总结(4)D:永久性 Durability愿你享受温暖感受爱,sincerely,end.

前言

认为自己大学时学得不够深入,发现实际工作中需要用到它的地方很多。因此记下此文帮助自己梳理知识,也希望可以给需要的你提供帮助。自学之路,如有错误,请纠正,万分感谢


来自笔者内心理解(以及结合相关文献 综合思考后)的正文:

数据库事务

一、定义

数据库事务是一个不可分割的工作单位,由事务开始与事务结束之间执行的全部数据库操作构成,这些操作要么全部执行,要么全部不执行。

二、要求

一个数据库事务可以包含多个查询、修改、删除、插入等数据库动作,它们要么作为一个整体完全得到确认,要么完全失败;一个事务只能包含对一个数据库实例的数据操作,跨多个数据库实例需要分布式事务的支持。

三、影响

数据库事务会给数据库并发操作带来一定影响,降低系统的并发能力。

四、特性(ACID)

(1)A:原子性 Atomicity

一个原子事务中的所有操作要么全部成功,要么全部失败。即整个事务中的每项任务都必须正确执行,如有任一任务执行失败,则整个事务就会被终止,此前对数据所作的任何修改都将被撤销(回滚);如果每项任务都执行成功,事务则会被提交。是数据库系统区别于其他一切文件系统的重要特性之一(文件系统出错不可恢复)。

看个小例子吧~

假如我们需要进行转账服务,以下表格中的每一步都需要保证全部正确,否则需要回滚到初始状态

(2)C:一致性 Consistency

数据库总是从一个一致性的状态转换到另一个一致性的状态。

承接上个小例子~

我们的转账服务中转出账户的扣除金额与转入账户的转入金额必须保持一致。

(3)I:隔离性 Isolation

针对并发事务而言,事务必须在不干扰其他进程或事务的前提下独立执行。(有级别设置)即要隔离并发运行的多个事务之间的影响。

写在前面的两个关键:共享锁排他锁,是实现隔离级别的两种锁模式,都为悲观锁①。

共享锁[S锁_shared lock]:

 是一种读锁。

 当事务A对数据对象B加S锁时,事务A可以读B但不能修改B,其他事务也能对B加S锁,但不能加X锁,直到A释放B上的S锁。

 这保证了其他事务在A释放B上的S锁之前对B可读,但不可写。

排他锁[X锁_exclusive lock]:

 是一种写锁。

 当事务A对临界区B加X锁时,事务A可以读写B,但其他事务不能对B加任何锁(共享锁,排他锁),直到A释放B上的X锁。

 这保证了其他事务在A释放B上的X锁之前不能对B进行读写。

总结:

 共享锁保证大家可以一起做只读操作(e.g. select),不可以有人再写入;

 排他锁保证只能一个人去处理数据(用于数据修改,e.g. insert、update、delete),其他人不能读写。

 X锁比S锁有更高的优先级,一个X锁请求可能会被插入到S锁队列的前面,但S锁不能插入到X锁前面。

注释(可跳过):实现并发控制的主要手段大致可以分为乐观并发控制和悲观并发控制两种。

①悲观锁:

在操作数据时,认为此操作会出现数据冲突,所以在每次操作都需通过获取锁才能进行。

方法由数据库自己实现,用的时候,直接调用数据库相关语句就可以。

场景适用于冲突频率高、重试代价大的场景,为数据处理的安全提供了保证。

缺点会降低并行性,需耗费较多的时间,增加产生死锁的机会。

 乐观锁:

在操作数据时,不认为此操作会出现数据冲突(不加锁),在操作结束后再判断是否有冲突。

方法需要我们自己实现,可以使用版本号等机制,数据库不自带。

场景适用于读操作多、响应效率高的场景,可以提高程序的吞吐量。

缺点锁的粒度如果掌握不好,更新失败的概率会比较高。

事务的隔离级别及解决方案

上表中,在相同运行环境下,不同隔离级别的顺序按照并发性由高到低,隔离性由低到高排序。

注释(也许看完注释之后依旧云里雾里,that’s OK,我们还有小例子在后面):

②脏读:事务A读取到了事务B没有提交的数据

③不可重复读:在事务A中,两次读取同一数据,得到的内容不同

④幻读:在事务A中,相同操作读取两次,得到的记录数不同

由下列例子帮助我们更好的理解事务的隔离级别:

1.未提交读

加锁机制:在写事务时加行级共享锁,读事务时不加锁

例子:事务A修改了一条记录的内容,但是并没有提交(commit),在隔离级别为未提交读的情况下,事务B可以读取到A修改后并未提交的记录内容。(由于是共享锁,写事务未提交前其他事务仍然能读)

有何影响呢?一旦A执行回滚操作(没有commit之前都是可以回滚的),B之前所读取的记录内容则为脏数据,这就造成了脏读。[不仅脏读无法避免,不可重复读(下面2.已提交读中介绍)、幻读(下面3.可重复读中介绍)也无法避免]

2.已提交读

是如何避免脏读的呢?加锁机制:写事务时加行级排他锁,事务结束才释放;读事务时加行级共享锁,读完立即释放锁(不等到整个事务结束后才释放)。(确保写一行时其他事务无法读写此行,只有commit以后才可读写,读一行时其他事务只能读,无法写这一行)

例子:事务A查询一条记录后,并没有结束事务A,在隔离级别为已提交读的情况下,接着事务B修改了A刚才查询的那条记录(既然是已提交读,那B修改内容后需要commit)。

有何影响呢?当A又再次查询这条记录时,发现与之前查询的记录不同(因为事务A没结束的时候B修改了内容,导致事务A两次读取不一致)。前后查询的记录不一就造成了不可重复读。[不仅不可重复读无法避免,幻读(下面3.可重复读中介绍)也无法避免]

3.可重复读

是如何避免不可重复读的呢?加锁机制:写事务时加行级排他锁,读事务时加行级共享锁,都持续到事务结束才释放。(确保整个事务中写就是写,读就是读,整个事务读完之后才可以写)

例子:事务A根据条件查询一组记录,之后事务B在A查询条件的记录范围内插入一条记录。

有何影响呢?当A又使用相同的方式再次对表进行检索时,却发现了一条新纪录。这个新记录对A来说就像突然出现的一样,这就造成了幻读。(读写事务只是加了行级锁,其他事务虽然不能修改这些行,但是能添加新行,因此出现幻读现象)

4.可串行化

是如何避免幻读的呢?加锁机制:读事务时加表级共享锁,写事务时加表级排他锁。(避免其他事务对该表的操作)

总结

(4)D:永久性 Durability

一旦事务提交成功,它对于数据的修改就会永久保存到数据库中,此时即使系统崩溃,修改的数据也不会丢失(磁盘损坏不包括,需要靠备份等)。


愿你享受温暖感受爱,sincerely,end.

如果觉得《数据库事务的四大特性 四种隔离级别 如何避免脏读 不可重复读 幻读(如何加锁)?》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。