MySQL事务事务存在的原因事务存在的目的:保证用户对数据操作对数据是安全的。(比如说银行卡余额) 事务的特性——ACID原子性:一个事务要么全部执行,要么不执行 一致性:事务开始和结束时,数据保持一致 隔离性:事务之间互不影响 持久性:事务操作的结果具有持久性 关于脏读,不可重复读,幻读
小结: 脏读是读取了尚未提交的数据,不可重复读是读取了不停更新的数据(修改),幻读是指读取了不停更新的数据(新增)。 关于事务隔离级别目的:避免脏读,不可重复读,幻读 读未提交:一个事务可以读到另一个事务尚未提交的数据。也就是脏读,避免脏读的方式: 读提交:一个事务要等另一个事务提交后才能读取数据。但会导致一个事务中相同查询出现不同的结果。也就是不可重复读。避免不可重复读的方式: 重复读(RR,MySQL默认级别):就是在开始读取数据时,不允许修改操作。但会导致由于允许insert操作导致的事务结果出现不同。也就是幻读,避免幻读的方式:: 序列化:序列化使事务串行顺序执行,但会大大降低并发性能。 MySQL锁机制Innodb实现了两种类型的行锁:共享锁,排他锁。 共享锁和排他锁共享锁:允许一个事务读一行,阻止其他事务获得相同数据集的排他锁,多个共享锁是可以并行的。 排他锁:获取排他锁的事务允许更新数据,阻止其他事务获取相同数据集的共享锁和排他锁。 【复述一下】 假设事务A获取了表中的行666,就相当于获得了共享锁,此时A可以读取数据,其他事务也可以获得行666的共享锁,所以多个共享锁是可以并行指的是多个事务可以读取相同的行,但是一旦某行被获取了共享锁,就无法被其他事务获取排他锁,也就是说,行只能读,不能写。 然后A读完了,事务B要对行666进行更新操作,就需要先获得排他锁,获得排他锁之后,其他事务就无法获取行666的排他锁和共享锁,也就是说,在事务B更新数据的时候不允许其他事务读或者更新。 所以排他锁就是指只允许一个事务进行写操作,在这个过程中,不允许其他事务读,也不允许其他事务写。 也就是说,排他锁是串行的,不能被多个事务同时持有,但共享锁可以。 【如何使用行锁】 InnoDB行锁是通过索引上的索引项来实现的,InnoDB这种行锁实现特点意味者:只有通过索引条件检索数据,InnoDB才会使用行级锁,否则,InnoDB将使用表锁!(这也是为什么需要进行索引优化的原因) 【行锁定的范围问题】 行锁:对索引项加锁,锁定一条记录 间隙锁:
间隙锁的目的是为了防止幻读 innodb自动使用间隙锁的条件:
Next-key Lock:等于行锁加间隙锁。扫描索引记录后,先对索引记录加上行锁,再对索引两边的间隙加上间隙锁。 意向共享锁和意向排他锁Innodb虽然使用行锁,但并没有废弃表锁。 【行锁和表锁】 MyISAM存储引擎使用的是表锁,而Innodb增加了行锁。并不意味着Innodb彻底抛弃了表锁。 关于行锁,较小的粒度导致其高并发,但也因较小的粒度导致加锁慢,开销大,会出现死锁情况。 关于表锁,较大的粒度在高并发上的表现很弱,但同时粒度较大,加锁块,开销小,不会出现死锁情况。 没有完美的技术,只有合适的解决方案。在高并发场景下使用行锁而忍受一些问题本质上是一种权衡。 【意向锁的背景冲突】 意向锁的出现本质上是解决行锁和表锁矛盾的问题。 事务A获得了表中某一行的共享锁,事务B申请了表的写权限,这时候就会产生矛盾。 【关于意向锁】 首先,意向锁是一种表锁。 意向共享锁:事务获得表中的某一行的共享锁前,需要先获得整张表的意向共享锁。 意向排他锁:事务获得表中的某一行的排他锁前,需要先获得整张表的意向排他锁。 意向锁的加锁过程是自动完成的。 【意向锁的共享问题】 意向锁是表锁,它的互斥性是针对表级别的事务,比如一个事务要获取一张表的写权限。所以意向锁对于表级别的事务是互斥的。但是对于行级别的事务是共享的,也就是说,一个意向锁可以被多个行级别的事务所持有。 死锁
死锁本质上就是持有锁和释放锁的问题,就像这个视频里描述的,面试官在听到死锁的解释后,才会释放offer这个锁,而应聘者是得到offer后才会释放死锁解释这个锁。offer和对死锁的解释就可以类比两个锁。 死锁的状态就是互相等待。 |
|