热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

想到数据库的事务问题,我横竖睡不着

longtimenosee!!距离上一次写东西已经已经是上一次了,是有写一些东西的必要了。特别是在遇到数据库的时候,脑子里

long time no see!!

距离上一次写东西已经已经是上一次了,是有写一些东西的必要了。

特别是在遇到数据库的时候,脑子里歪歪斜斜的冒出两个字“事务”,我横竖睡不着,想要好好把事务这个小石子从鞋里翻出来。

事务很重要,有多重要。

互联网大数据时代,数据是最基本的,没有数据,互联网就是空谈。

那么保证数据操作的安全,就是互联网的核心。

操作数据就需要操作数据库,而事务就成了保证数据库数据安全的护城河。


一、什么是事务?

事务是操作数据库的基本单位,操作数据库一次,也就进行了一次事务。

在我的理解,事务由一个,或多个sql语句构成。

一次数据库事务的执行有成功有失败,就会存在一个问题。

例如有A,B两条sql语句同时对100块进行操作,A执行成功,100-100=0。

异常示例

而B需要实现100-100+100=100的操作时,出现异常,导致,B执行失败。

如果发生在银行,银行损失100块,如果发生在用户,用户损失一百块。

事务的存在解决了这个问题,AB两个sql都存在于一个事务中。

事务中的sql要么都执行成功,要么都失败。

回滚示例

B失败,A也不会成功,0元会回滚到100块,也就是没有操作的原始状态。

数据库不能没有事务, 就像西方不能没有耶路撒冷。


二、事务的特性

事务的特性可以理解为事务的特点,以下四点。

1.原子性:原子是万事万物最小的单位,所以对数据库而言,事务就是最小的操作单位,不可再拆分。事务中的sql语句要么一起失败,即事务提交(commit)和事务回滚(rollback)。

2.隔离性:不允许多个线程同时操作一个session的数据。例如a,b两个人,a在操作数据的时候还未提交,b就不能操作。a和b同时处在两个不同的事务。

3.持久性:事务一旦提交,就不能回滚。

4.一致性:和能量守恒一样,事务提交前后需要保证数据守恒,增加的和减少的需要一致。

事务的这四个特性,保证了操作数据库数据的安全性。


三、事务的并发问题

只有一个线程操作数据,肯定没有什么问题。而一旦线程变多,就需要考虑并发问题。

何为并发问题?

例如还是100块,C线程进行了+5的操作,此时,C还没有提交,而D线程做了-5的操作,并且提交了。

最后提交过后的C看到还是100块。

并发会造成数据覆盖,所以要解决并发问题,并发问题有以下几种。

AB线程,A负责写,B负责读。

脏读:A正在修改数据,还没有提交,此时B读取了该数据。A如果回滚,B读到的就是一个不存在的数据。脏读也就是读取到了别人还未提交的数据。

脏读示例

不可重复读:B第一次读到了原始数据,接着A开始修改数据,B再次读取,则读到了修改后的数据,前后两次数据不一致。

不可重复读示例

幻读:AB线程同时对某个资源进行操作。A插入一个数字1,此时B线程删除了数字1。最后A发现数字1不见了,像是产生了幻觉,什么鬼!!

幻读读示例

需要知道:不可重复读侧重 读-读,幻读侧重 读-写

四、事务的隔离等级

为了解决以上的问题,事务有应对的措施,也就是隔离等级,隔离等级如下:

读未提交(Read Uncommitted):最低的隔离等级,顾名思义,该隔离等级下,线程可以读到其他线程还没有提交的数据。虽然支持超高并发操作,但数据库操作一般不用这个等级,没什么用。

读已提交(Read-commited):这是大部分数据库正在使用的隔离等级(oracle),只能读到其他线程提交了的数据,避免了脏读,但仍然会出现不可重复度和幻读问题。

可重复读(Repeatable Read):mysql默认的事务隔离等级。处在该隔离等级,读到的数据都是一致的。原理是事务执行期间,会锁定该事务引用的所有行,其他事务不能做修改。但仍然存在幻读。

串行化(serializable):最高级别的隔离等级,解决了所有并发问题,但速度极慢。

事务的隔离等级不是越高越好,也不是越低越好。越高,虽然数据安全,但是牺牲了性能,越低,性能好了,数据的安全性得不到保证。

应针对不同的环境应该设置不同的隔离等级,例如对于银行系统和其他后台管理系统事务隔离等级肯定有出入。

此外,不同的数据库隔离等级是不同的,oracle和mysql一个是Read-commited,一个是Repeatable Read。oracle抛弃了一些安全性能,但提高了操作性能。

作为程序从业人员,一般我们不去修改数据库默认的隔离等级。因为数据库的隔离等级一定是设计者经过了多方的考虑,得到的一个最优解。


推荐阅读
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • MySQL中的MVVC多版本并发控制机制的应用及实现
    本文介绍了MySQL中MVCC的应用及实现机制。MVCC是一种提高并发性能的技术,通过对事务内读取的内存进行处理,避免写操作堵塞读操作的并发问题。与其他数据库系统的MVCC实现机制不尽相同,MySQL的MVCC是在undolog中实现的。通过undolog可以找回数据的历史版本,提供给用户读取或在回滚时覆盖数据页上的数据。MySQL的大多数事务型存储引擎都实现了MVCC,但各自的实现机制有所不同。 ... [详细]
  • Oracle Database 10g许可授予信息及高级功能详解
    本文介绍了Oracle Database 10g许可授予信息及其中的高级功能,包括数据库优化数据包、SQL访问指导、SQL优化指导、SQL优化集和重组对象。同时提供了详细说明,指导用户在Oracle Database 10g中如何使用这些功能。 ... [详细]
  • Oracle10g备份导入的方法及注意事项
    本文介绍了使用Oracle10g进行备份导入的方法及相关注意事项,同时还介绍了2019年独角兽企业重金招聘Python工程师的标准。内容包括导出exp命令、删用户、创建数据库、授权等操作,以及导入imp命令的使用。详细介绍了导入时的参数设置,如full、ignore、buffer、commit、feedback等。转载来源于https://my.oschina.net/u/1767754/blog/377593。 ... [详细]
  • Python SQLAlchemy库的使用方法详解
    本文详细介绍了Python中使用SQLAlchemy库的方法。首先对SQLAlchemy进行了简介,包括其定义、适用的数据库类型等。然后讨论了SQLAlchemy提供的两种主要使用模式,即SQL表达式语言和ORM。针对不同的需求,给出了选择哪种模式的建议。最后,介绍了连接数据库的方法,包括创建SQLAlchemy引擎和执行SQL语句的接口。 ... [详细]
  • 从Oracle安全移植到国产达梦数据库的DBA实践与攻略
    随着我国对信息安全和自主可控技术的重视,国产数据库在党政机关、军队和大型央企等行业中得到了快速应用。本文介绍了如何降低从Oracle到国产达梦数据库的技术门槛,保障用户现有业务系统投资。具体包括分析待移植系统、确定移植对象、数据迁移、PL/SQL移植、校验移植结果以及应用系统的测试和优化等步骤。同时提供了移植攻略,包括待移植系统分析和准备移植环境的方法。通过本文的实践与攻略,DBA可以更好地完成Oracle安全移植到国产达梦数据库的工作。 ... [详细]
  • 如何在php文件中添加图片?
    本文详细解答了如何在php文件中添加图片的问题,包括插入图片的代码、使用PHPword在载入模板中插入图片的方法,以及使用gd库生成不同类型的图像文件的示例。同时还介绍了如何生成一个正方形文件的步骤。希望对大家有所帮助。 ... [详细]
  • 推荐一个ASP的内容管理框架(ASP Nuke)的优势和适用场景
    本文推荐了一个ASP的内容管理框架ASP Nuke,并介绍了其主要功能和特点。ASP Nuke支持文章新闻管理、投票、论坛等主要内容,并可以自定义模块。最新版本为0.8,虽然目前仍处于Alpha状态,但作者表示会继续更新完善。文章还分析了使用ASP的原因,包括ASP相对较小、易于部署和较简单等优势,适用于建立门户、网站的组织和小公司等场景。 ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • MyBatis错题分析解析及注意事项
    本文对MyBatis的错题进行了分析和解析,同时介绍了使用MyBatis时需要注意的一些事项,如resultMap的使用、SqlSession和SqlSessionFactory的获取方式、动态SQL中的else元素和when元素的使用、resource属性和url属性的配置方式、typeAliases的使用方法等。同时还指出了在属性名与查询字段名不一致时需要使用resultMap进行结果映射,而不能使用resultType。 ... [详细]
  • 如何在php中将mysql查询结果赋值给变量
    本文介绍了在php中将mysql查询结果赋值给变量的方法,包括从mysql表中查询count(学号)并赋值给一个变量,以及如何将sql中查询单条结果赋值给php页面的一个变量。同时还讨论了php调用mysql查询结果到变量的方法,并提供了示例代码。 ... [详细]
  • Oracle优化新常态的五大禁止及其性能隐患
    本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
  • 本文介绍了一个误删Oracle数据文件导致数据库无法打开的问题,并提供了解决方式。解决方式包括切换到mount状态、离线删除报错的数据文件等。 ... [详细]
  • 在Oracle11g以前版本中的的DataGuard物理备用数据库,可以以只读的方式打开数据库,但此时MediaRecovery利用日志进行数据同步的过 ... [详细]
  • 本文介绍了Oracle存储过程的基本语法和写法示例,同时还介绍了已命名的系统异常的产生原因。 ... [详细]
author-avatar
郭倩尔偏执起来不是人_
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有