mysql数据库事务知识点记录

 一、事务的ACID特性:

  1. 原子性(atomicity):同一个事务里面的操作,要么全部成功,要么全部失败,不存在部分成功部分失败。
  2. 一致性(consistency):事务必须从一个一致性状态转变到另外一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。那转账举栗子,A账户和B账户之间相互转账,无论如何操作,A、B账户的总金额都必须是不变的。
  3. 隔离性(isolation):隔离性是指多个事务并发访问数据库时,相互之间不能干扰,mysql数据库有4种隔离级别,读未提交、读已提交、可重复读、串行化,后面会对这4种隔离级别详细介绍。
  4. 持久性(durability):一旦事务提交,那么它对数据库中的对应数据的状态的变更就会永久保存到数据库中。--即使发生系统崩溃或机器宕机等故障,只要数据库能够重新启动,那么一定能够将其恢复到事务成功结束的状态。

二、不考虑隔离性时可能会出现的问题:

  1. 脏读:

     脏读是指一个事务在处理数据的过程中,读取到另一个为提交事务的数据。

    --原数据
    --id    name
    --1     allen
     
    --事务1
    START TRANSACTION;
    updata t_table set name = 'bob' where id = 1;    --此时事务2查询id = 1
    ROLLBACK;
     
    --事务2
    select * from t_table where id = 1;        --查询到 id = 1, name = 'bob'

    事务1并没有提交,name 还是 allen,但是事务2却读到了 name = bob,这就是脏读。如果换成A给B转账,B查询到了没有提交的事务,认为已经收到A转过来的钱,那岂不是很恐怖。

    不过在实际开发中,应该很少有人会犯这样的低级错误。

  2.  不可重复读:
    不可重复读是指对于数据库中的某个数据,一个事务范围内的多次查询却返回了不同的结果,这是由于在查询过程中,数据被另外一个事务修改并提交了。
     
    
    --原数据
    --id    name
    --1     allen
     
    --事务1
    select * from t_table where id = 1;    -- 查询到 id = 1, name = allen, 事务2在此时提交
    select * from t_table where id = 1;    -- 查询到 id = 1, name = bob
     
    --事务2
    start transaction;
    update t_table set name = 'bob' where id = 1;
    COMMIT;
    

    不可重复读和脏读的区别是,脏读读取到的是一个未提交的数据,而不可重复读读取到的是前一个事务提交的数据。

    而不可重复读在一些情况也并不影响数据的正确性,比如需要多次查询的数据也是要以最后一次查询到的数据为主。

  3.  幻读:

    幻读是事务非独立执行时发生的一种现象。例如事务T1对一个表中所有的行的某个数据项做了从“1”修改为“2”的操作,这时事务T2又对这个表中插入了一行数据项,而这个数据项的数值还是为“1”并且提交给数据库。而操作事务T1的用户如果再查看刚刚修改的数据,会发现还有一行没有修改,其实这行是从事务T2中添加的,就好像产生幻觉一样,这就是发生了幻读。

    幻读和不可重复读都是读取了另一条已经提交的事务(这点就脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)。
     

    
    --原数据
    --id    name
    --1     allen
     
    --事务1
    select * from t_table where id = 1;    --返回[id = 1, name = allen]  此时事务2提交
    select * from t_table where id = 1;    --返回[id = 1, name = allen],[id = 1, name = bob]
     
     
    --事务2
    insert into t_table values(1,'bob');
    

    不可重复读和幻读是初学者不易分清的概念,我也是看了详细的解读才明白的,总的来说,解决不可重复读的方法是 锁行,让查询出来的所有行不能update和delete;解决幻读的方式是 锁表或者锁某一个范围;让这个范围内的所有数据不能insert,update和delete

三、4种不同隔离级别所能解决的问题:

脏读不可重复读幻读
读未提交×××
读已提交××
可重复读×
串行化

以上4种隔离级别,越往下数据库隔离级别越高,相应的性能也就越低,其中读未提交和串行化一般不推荐使用,具体使用哪种隔离级别需要分析业务,看适合使用哪种隔离级别,mysql默认的隔离级别时“可重复读”。

mysql的事务主要解决两件事:

1.session 想要执行的操作是否能够继续进行下去?(与锁相关).

2.如果能执行下去,并且执行的是select,那么select返回的数据是数据库最新数据还是快照数据.

mysql事务的实现方式是基于innodb的锁,详细原理参考文档:

https://www.cnblogs.com/leohahah/p/8863422.html

关于mysql锁的几点基础的小总结(在事务隔离级别"可重复读"情况下):

1.事务中的任何操作需要执行前,都会先对数据进行上锁,如果上锁时发现已经有其他事务对这些数据上了锁,就会阻塞等待锁的释放;

2.事务中select ... from ... 查询不会上任何锁();

3.事务中select ... form ... lock in share mode 会对查询到的数据上读锁;

4.事务中insert/update/delete ... where ... 会对操作的记录上写锁,如果where 中的条件能用到索引并且是范围条件的话(例如 where id>0 and id<10),如果表里只有id=3 和 id=4的两条数据在范围内,那么id=3和id=4两条数据会被上行锁,id=(0,2]和[5,10)这两个范围会被上间隙锁(gap lock),类似于锁住了不存在的行,当其他事务进行insert into ... (id,...) values (6,...)或者update  ... set id = 6 这种id在这个被锁住的范围内的sql时,执行会被阻塞.

5.事务上的锁具体时行锁还是表锁,取决于这条语句在执行select/update/delete前是否能够通过索引获取到精确的行记录主键ID,如果能获取到就是行锁,不能获取到就是表锁.

6.insert操作本身会自己产生主键,并不需要主键ID,所以insert操作一定可以对自己插入的数据上行锁.

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值