事务的特性、事务的隔离性。脏读、不可重复读、幻读

事务

一个事务是一个完整的逻辑单元 ,不可以再分。
比如 银行用户转账,A账号给B账号转账1000元,A账户里的余额需要减少一千元,
B账户余额需要增加一千元,这是两条更新语句,这两条更新语句只能有两种结果,
要么同时成功,要么同时失败。那么在这个过程中需要用到数据库的“事务机制”

事务的特性

事务包括四大特性
原子性:事务是工作的最小单元,一个事务不能再分割
一致性:事务必须保证多条DML语句同时成功,或者同时失败
隔离性:事务和事务之间不能相互干扰。
永久性:最终的数据必须持久化到硬盘文件中。

事务的隔离性

  • 第一级别:读未提交
    事务读取的是另一个事务未提交的数据,,容易产生脏读
  • 第二级别:读已提交
    事务读取的是另一个事务已经提交的数据,解决了脏读,但是会产生不可重复读
  • 第三级别:可重复读 (MySQL数据库默认的隔离级别)
    不会产生脏读、不可重复读,但是会产生幻读。
  • 第四级别:序列化读/串行化读
    将事务进行了排队,一个事务没有结束,另一个事务不能开始
    解决了脏读,不可重复读,幻读。
    但是这样执行效率会变低。

脏读 不可重复读 幻读

  1. 脏读:脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
    例如:
    张三的工资为5000,事务A中把他的工资改为8000,但事务A尚未提交。
    与此同时,
    事务B正在读取张三的工资,读取到张三的工资为8000。
    随后,
    事务A发生异常,而回滚了事务。张三的工资又回滚为5000。
    最后,
    事务B读取到的张三工资为8000的数据即为脏数据,事务B做了一次脏读。
  2. 不可重复读:是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
    例如:
    在事务A中,读取到张三的工资为5000,操作没有完成,事务还没提交。
    与此同时,
    事务B把张三的工资改为8000,并提交了事务。
    随后,
    在事务A中,再次读取张三的工资,此时工资变为8000。在一个事务中前后两次读取的结果并不致,导致了不可重复读。
  3. 幻读:
    具体看以下实例
    (1) 事务A
    # 设置事务的隔离级别是可重复读,并开启事务A;
    mysql> set session transaction isolation level repeatable  read;
    mysql>start transaction;
    mysql> select * from jmeter_contacts where id = 1;
    Empty set (0.00 sec)
    
    以上结果可以发现在A事务中没有查询到A等于1的数据;现在打开另一个窗口,开启事务B
    (2)事务B
    # 设置事务的隔离级别是可重复读,并开启事务A;
    mysql> set session transaction isolation level repeatable  read;
    Query OK, 0 rows affected (0.00 sec)
    mysql> start transaction;
    Query OK, 0 rows affected (0.00 sec)
    #向表中插入id为1的数据,并提交事务
    mysql>  insert into jmeter_contacts (id,  user_id ,dingding_token,is_deleted) values  (1, 123,  'adadas', 0 );
    Query OK, 1 row affected (0.00 sec)
    
    mysql> commit;
    Query OK, 0 rows affected (0.00 sec)
    
    
    (3) 接下来事务A再次查询id为1的数据
    mysql> select * from jmeter_contacts where id = 1;
    Empty set (0.00 sec)
    
    # 因为是可重复读,所以还是没有查询到数据;
    # 那接下来让我们同样在数据库中插入id为1的数据,
    mysql> insert into jmeter_contacts (id,  user_id ,dingding_token,is_deleted) values  (1, 123,  'adadas', 0 );
    ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
    
    
    这时,问题就暴露出来了,明明我在本事务中没有
    查询到id为1的数据,为啥还是不能插入id为1的数据呢?
    难道是我的查询产生幻觉了?
  • 15
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值