圣诞网站怎么做,东莞哪家网站建设专业,网站快速优化排名官网,wordpress好还是事务概述
事务是数据库区别于文件系统的重要特性之一#xff0c;当我们有了事务就会让数据库始终保持一致性#xff0c;同时我们还能通过事务机制恢复到某个时间点#xff0c;这样可以保证已提交到数据库的修改不会因为系统崩溃而丢失。
1、基本概念
事务#xff1a;一组…事务概述
事务是数据库区别于文件系统的重要特性之一当我们有了事务就会让数据库始终保持一致性同时我们还能通过事务机制恢复到某个时间点这样可以保证已提交到数据库的修改不会因为系统崩溃而丢失。
1、基本概念
事务一组逻辑操作单元是数据库从一种状态变换到另一种状态。
事务处理的机制保证所有的事务都作为一个工作单元来执行即使出项了故障都不能改变这种执行方式。当在一个事务中执行多个操作时要么所有的事务都提交commit,那么这些修改就永久的保存下来要么数据库管理系统将放弃所作的所有修改整个事务回滚rollback到最初状态
#案例AA用户给BB用户转账100
update account set money money - 100 where name AA;
update account set money money 100 where name BB;2、事务的ACID特性
原子性atomicity
原子性是指事务是一个不可分割的工作单元要么全部提交要么全部失败回滚。既要么转账成功要么转账失败是不存在中间的状态。如果无法保证原子性会怎么样就会出项数据不一致的情形A账户减去100元而B账户增加100元操作失败系统将无故丢失100元。
一致性consistency
一致性是指事务执行前后数据从一个合法性状态变换到另外一个合法性状态。这种状态是语义上的而不是语法上的跟具体的业务有关。
那什么是合法的数据状态呢满足预定的约束的状态就叫做合法的状态。通俗一点这状态是由你自己来定义的比如满足现实世界中的约束。满足这个状态数据就是一致性的不满足这个状态数据就是不一致的如果事务中的某个操作失败了系统就会自动撤销当前正在执行的事务返回到事务操作之前的状态。
举例1A账户有200元转账300元出去此时A账户余额为-100元。你自然就发现了此时数据是不一致的为什么呢因为你定义了一个状态余额这列必须0。
举例2A账户有200元转账50元给B账户A账户的钱扣了但是B账户因为各种意外余额并没有增加。你也知道此时数据是不一致的为什么呢因为你定义了一个状态要求AB的总余额 必须不变。
隔离性isolation
事务的隔离性是指一个事务的执行不能被其他事务干扰即一个事务内部的操作及使用的数据对并发的其他事务是隔离的并发执行的各个事务之间不能互相干扰。
如果无法保证隔离性会怎么样假设A账户有200元B账户0元A账户往B账户转账两次每次金额为50元分别在两个事务中执行。如果无法保证隔离性会出项下面的情形:
UPDATE accounts SET money money - 50 where NAME AA;UPDATE accounts SET money money 50 where NAME BB;事务1事务2从磁盘上将A账户余额读取到变量A中 A为200执行操作AA-50将A的值写回磁盘 A为150从磁盘中将B账户余额读取到变量B中 B为0执行操作BB50从磁盘上将A账户余额读取到变量A中 A为150执行操作AA-50将A的值写回磁盘 A为100从磁盘中将B账户余额读取到变量B中 B为0执行操作BB50将B值写回磁盘 B为50将B值写回磁盘 B为50
持久性durability
持久性是指一个事务一旦被提交它对数据库中数据的改变就是永久性的接下来的其他操作的数据库故障不应该对其他有任何影响。
持久性是通过事务日志来保证的。日志包括了重做日志和回滚日志。当我们通过事务对数据进行修改的时候首先会将数据库的变化信息记录到重做日志中然后再对数据库中对应的行进行修改。这样中的好处是即使数据库系统崩溃数据库重启后也能找到没有更新到数据库系统中的重做日志重新执行从而使事务具有持久性。
总结ACID是事务的四大特性在这四个特性中原子性是基础隔离性是手段一致性是约束条件而持久性是我们的目的。数据库事务其实就是数据库设计者为了方便起见把需要保证的原子性隔离性一致性和持久性的一个或多个数据库操作称为一个事务。
3、数据并发问题
针对事务的隔离性和并发性我们怎么做取舍呢先看一下访问相同数据的事务在不保证串行执行也就是执行完一个再执行另一个的情况下可能会出现哪些问题
1、脏写Dirty Write
对于两个事务SessionA、SessionB如果事务SessionA修改了另一个未提交事务SessonB修改过的数据那就意味着发生了脏写如图所示
发生时间编号SessionASessionB1Begin;2Begin;3UPDATE student SET name ‘李四’ WHERE studentno 1;4UPDATE student SET name‘张三’ WHERE studentno 1;5COMMIT;6ROLLBACK;
SessionA和SessionB各开启了一个事务SessionB中的事务先将studentso列为1的记录的name更新为‘李四’然后SessionA中的事务接着又把这条studentno列为1的记录的name列更新为‘张三’。如果之后SessionB中的事务进行了回滚那么SessionA中更新也将不复存在这种现象就称之为脏写。这时SessionA中的事务就没有效果了明明把数据更新了最后也提交事务了最后看到的数据没有变化。这里大家对事务的隔离级别比较了解的话会发现默认隔离级别下上面SessionA中的更新语句会处于等待状态这里只是跟大家说明一下会出现这样现象。
2、脏读Dirty Read
对于两个事务SessionA、SessionBSession A 读取了已经被Session B更新但还没有被提交的字段。之后若Session B回滚Session A 读取的内容就是临时且无效的。如图所示
发生时间编号SessionASessionB1Begin;2Begin;3UPDATE student SET name ‘张三’ WHERE studentno 1;4SELECT * FROM student WHERE studentno 1;(如果读取到列name的值为’张三’则意味着发生了脏读)5COMMIT;6ROLLBACK;
SessionA和SeesionB各开启了一个事务SessionB中的事务先将studentno列为1的记录的name列更新为‘张三’然后SessionA中的事务再去查询这条studentno为1的记录如果读取到列name的值为’张三‘而Session B中的事务稍后进行了回滚那么SessionA中的事务相当于读取到了一个不存在的数据这种现象就称之为脏读。
3、不可重复读Non-Repeatable Read
对于两个事务SessionA、SessionBSession A读取了一个字段然后SessionB更新了该字段之后Session A再次读取同一个字段值就不同了那就意味着发生了不可重复读。
发生时间编号SessionASessionB1Begin;2SELECT * FROM student WHERE studentno 1;(此时读到的列name的值为’王五‘)3UPDATE student SET name ‘张三’ WHERE studentno 1;4SELECT * FROM student WHERE studentno 1;(如果读到列name的值为’张三‘则意味着发生了不可重复读)5UPDATE student SET name ‘李四’ WHERE studentno 1;6SELECT * FROM student WHERE studentno 1;(如果读到列name的值为’李四‘则意味着发生了不可重复读)
我们在Session B中提交几个隐式事务注意是隐式事务意味着语句结束事务就提交了这些事务都修改了studentno列为1的记录的列name的值每次事务提交之后如果Session A中的事务都可以查看到最新的值这种现象就称之为不可重复读。
4、幻读Phantom
对于两个事务Session A、Session BSessionA从一个表中读取了一个字段然后SessionB在该表中插入 了一些新的行。之后如果Session A再次读取同一个表就会出多几行。那就意味着发生了幻读。
发生时间编号SessionASessionB1Begin;2SELECT * FROM student WHERE studentno0;(此时读取到的列name的值为’张三‘)3INSERT INTO student VALUES (2,‘赵六’,‘2班’)4SELECT * FROM student WHERE studentno0;(如果读取到了列name的值为’张三‘、’赵六‘的记录则意味着发生了幻读)
SessionA中的事务先根据条件studentno 0这个条件查询表student,得到了name的值为’张三‘的记录之后SessionB中提交了一个隐式事务该事务向表student中插入了一条新的记录之后SessionA中的事务再根据相同的条件studentno 0 查询表student得到的结果集中包含Session B中的事务新插入的那条记录这种现象也被称之为幻读。我们把新插入的那些记录称之为幻影记录。
注意1
有的同学会产生疑问那如果SessionB中删除了一些符合studentno 0的记录而不是插入新记录那Session A之后再根据studentno 0的条件读取的记录变少了这种现象算不算幻读呢这种现象不属于幻读幻读强调的是一个事务按照某个相同条件多次读取记录时后读取时读到了之前没有读到的记录。
注意2
那对于先前已经读到的记录之后又读取不到这种情况算啥呢这相当于对每一条记录都发生了不可重复读的现象。幻读只是重点强调了读取到了之前读取没有获取到的记录。
4、SQL中的四种隔离级别
上面介绍了几种并发事务执行过程中可能遇到的一些问题这些问题有轻重缓急之分我们给这些问题按照严重性来排一下序
脏写 脏读 不可重复读 幻读我们愿意舍去一部分隔离性来换取一部分性能在这里就体现在设立一些隔离级别隔离级别越低并发问题发生的就越多。SQL标准中设立了4个隔离级别
READ UNCOMMITTED读未提交在该隔离级别所有事务都可以看到其他未提交事务的执行结果。不能避免脏读不可重复读幻读。READ COMMITTED读已提交它满足了隔离的简单定义一个事务只能看见已经提交事务所做的改变。这是大多数数据库系统的默认隔离级别但不是MySQL默认的。可以避免脏读但不可重复读幻读问题仍然存在。REPEATABLE READ可重复读事务A在读到一条数据之后此时事务B对该数据进行了修改并提交那么事务A再读该数据读到的还是原来的内容。可以避免脏读不可重复读但幻读问题仍然存在。这是MySQL的默认隔离级别。SERIALIZABLE可串行化确保事务可以从一个表中读取相同的行。在这个事务持续期间禁止其他事务对该表执行插入更新和删除操作。所有的并发问题都可以避免但性能十分底下。能避免脏读、不可重复读和幻读。
SQL标准中规定针对不同的隔离级别并发事务可以发生不同严重程度的问题具体情况如下
隔离级别脏读可能性不可重复读可能性幻读可能性加锁读READ UNCOMMITTEDYesYesYesNoREAD COMMITTEDNoYesYesNoREPEATABLE READNoNoYesNoSERIALIZABLENoNoNoYes
Yes表示会出现的可能性No表示不会出现的可能性。
脏写没有涉及到因为脏写这个问题太严重了不论是哪种隔离级别都不允许脏写的情况发生。
不同的隔离级别有不同的现象并有不同的锁和并发机制隔离级别越高数据库的并发性能就越差。