何为事务?
事务(Transaction)是指一组操作的集合,这些操作要么全部执行成功,要么全部不执行。事务通常用于保证数据库的一致性、完备性和可靠性,确保数据的完备性与精确性。
有用避免部分执行,部分未执行而引起的问题;
引入例子:
假设以了局景: 转账
第一步A用户转账给B用户100元 账户-100
- -- 从账户A扣款
- UPDATE accounts SET balance = balance - 100 WHERE account_id = 'A';
复制代码 第二步B用户收到A转账100元 账户+100
- -- 向账户B存款
- UPDATE accounts SET balance = balance + 100 WHERE account_id = 'B';
复制代码 此时假如第一步完成之后,由于受到各种原因,例网络颠簸,主机关机,MySQL服务器瓦解等等因素,导致第二步未操作,这可丧失大了,A凭空丢失100,所以这种环境是不答应发生的。
此时由于是俩个操作,全部MySQL会将这俩个操作打包成一个操作(原子性),要么一起完成,要么都不完成。
假如中途发生异常,此时操作将会举行“回滚”操作,全部操作将会被撤销。
增补:MySQL会将每一步操作都会记录在MySQL的日志中,所以可以根据日志里面的内容举行还原操作
在 MySQL 中,事务是由多个 SQL 语句组成的一个操作单元,要么全部的操作都成功执行(提交,commit),要么在发生错误时,全部操作都不执行(回滚,rollback)。通过事务,MySQL 可以或许提供更强的错误恢复能力,并保证数据库在并发访问时的一致性。
事务的四大特性:
事务有四个核心特性,通常被称为 ACID 特性:原子性(Atomicity),一致性(Consistency),长期性(Durability),隔离性(Isolation);
原子性:
在上述操作中,将多个操作打包成一个操作时,此期间表这个操作具有“原子”的,原子就是从前最小的单元,不可拆分。
事务中的操作要么全部成功,要么全部失败。原子性确保了事务是最小的执行单元,无法再分割。纵然在事务执行的过程中发生故障,数据库也会通过回滚操作使事务的状态恢复到事务开始之前。
一致性:
在执行事务开始前后,要保证数据是一致的,不会出现对不上的环境。一旦触发“回滚”操作,也要保证回滚回去的数据跟原来一样;
事务执行前后,数据库的状态必须从一个一致的状态转变到另一个一致的状态。全部事务都必须遵循数据库的完备性约束,如主键、外键等,确保数据的完备性和正确性。
长期性:
一旦事务提交,它对数据库的更改是永世性的,纵然发生体系瓦解或断电,提交的事务所做的更改也会保留下来。
隔离性:
在并发环境下,多个客户端同时对服务器发起事务请求,一个事务的执行不应受到其他事务的干扰。每个事务应该像是在独占数据库一样执行,直到它提交或回滚。
在并发环境下,大概会产生以下问题:脏读,不可重复读,幻读;
脏读:
脏读指的是一个事务读取了另一个事务尚未提交的数据。这大概会导致读取到不一致的数据,因为另一个事务大概回滚,使得当前事务读取的数据变得无效。
例子:
假设有一场随堂考试,小明(学渣)抄袭小强(学霸)的试卷(这种举动是欠好的,只是比喻),此时小强写完了试卷给小明抄,小明写着写着写完了之后,小明就直接提交试卷了。但小强在查抄试卷的时间,发现查抄试卷的时间很多答案填错了,那么小强肯定将答案改正了返来 ,而小明吃了大亏,内心想我*****,还不如本身写...................
核心在于:当小强不光写完试卷,并且还查抄完毕,确保不会修改的环境下,小明再去抄写他的答案,不然都大概堕落
解法方法:
当事务B查看事务A(写操作)的数据时间,将事务A的数据举行“加锁”,此时势务B不能查看A的数据,必须等待事务A确定下来,才可以查看。
这就相当于降低了 '并发能力',也就降低了数据库服务器的处理服从,提高了 '隔离性' ,也提高了数据的正确性。在并发执行事务过程中,相互之间是相互影响的,彼此的影响越小,隔离性越高;反之影响越大,隔离性越低。
不可重复读
在上述底子上,我们已经把写操作加上锁,这就意味着读操作的事务不能中途查询,以免没有查询到最闭幕果。
例子:
当我们写博客的时间,此时读者必须等我们发布完成之后,才华阅读我们的博客。
假设我们写完已经发布了 这是事务A
然后读者去查看博客的内容 这是事务B
当我们发布完 我们还觉得内容必要修改一下 大概存在一点问题 又举行发布了 这是事务C
问题出现在事务B此时在读数据的时间,此时我们事务C也执行了,假设博客页面革新了,事务B发现此时读到的数据跟刚才读到的数据不一样,这就是不可重复读问题;
解法:
在事务B读操作的时间 ,我们也不能执行事务C,必须等事务B执行完之后,才华修改数据,也就是说在“读数据”的时间也不能“写数据”;
所以对事务B读操作也加上“锁”,就可以保证事务 B 前后两次读取的数据都是一致的。
脏读和不可重复读的区别:
- 脏读关注的是一个事务读取另一个事务未提交的数据,且这个数据大概最终会被回滚,因此它是不可靠的。
- 不可重复读关注的是同一个事务内,在多次读取同一数据时,数据发生了变化(通常是由于其他事务的提交),导致读取结果不一致。
幻读:
幻读是指一个事务在查询数据时,其他事务大概插入、删除或修改记录,导致该事务查询的数据集发生变化,即查询结果出现"幻象"。在一个事务中,查询的结果集在差别的查询操作之间大概不一致。
例子:
刚才约定对读和写操作举行加上锁。
事务A发布第一篇博客
事务B在查询博客的内容
此时我们并不修改第一篇博客的内容,闲着也是闲着,于是我们继续写了新的一篇博客,第二篇博客。 事务C
在B再一次查询的时间,发现了多出来了一篇博客,此时就是幻读。
解法:
当读者在阅读博客的时间,叫我们啥事别做了,好好苏息,简朴来说,就是一个事务一个事务来,在执行事务的时间,不要执行任何操作;
实现串行化操作,此时没有并发了,因此服从最低,并且也是隔离性最高的,数据是最正确的。
隔离性的隔离级别:
隔离级别脏读不可重复读幻读实用场景读未提交(Read Uncommitted)是是是高并发、无需完全一致性的数据场景读已提交(Read Committed)否是是实用于实时性要求较高的场景可重复读(Repeatable Read)否否是实用于大部分应用,默认隔离级别串行化(Serializable)否否否保证最大程度的一致性,但性能最低 总结
- 脏读、不可重复读和幻读都是由于并发事务相互干扰所导致的问题。为了避免这些问题,可以选择符合的事务隔离级别:
- 读未提交:出现脏读,不可重复读,幻读。
- 读已提交:防止脏读,但大概会出现不可重复读和幻读。
- 可重复读:防止脏读和不可重复读,但大概会出现幻读。
- 串行化:完全避免全部并发问题,但性能最差。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |