事务
事务是一种工作机制,他将所有要执行的操作,放到一个不可分割的执行单元里。当所有操作都完成,这个事务才叫完成,否则需要回滚,回到最初的状态。
事务四大特性:ACID
- 原子性(atomicity)
一个事务要么全部提交成功,要么全部失败回滚。
- 一致性(consistency)
一个事务在执行之前和执行之后,数据完整性一致。eg.A有1000元给B转200,B本来有800,现在变为1000元 前:A+B=1800元 后:800+1000=1800,数据始终在1800元,最终一致性不变。
- 隔离性(isolation)
指在并发条件下,每个事务执行操作都是独立,对其他事务是不可见的。就如隔离了一样,隔离分为4个隔离级别,Read Uncommitted、Read committde、Repeatabl Read ,serializable。
在事务中不同个隔离级别是为了解决某些问题的,一般会出现如下3个问题
脏读,不可重复,幻读。
- 脏读:同时有A,B两个事务 ,只要B事务有增删改等操作时,A可以立马读到,如果B事务可能会回滚,或者其他操作,A这时候读到的数据可能是脏数据,所以被称为脏读。
- 不可重复读:同时有A,B两个事务,B事务插入提条数据,A这时候select没有B刚刚插入的数据,如果B提交了。A再次select,突然有了。
- 幻读:同时有A,B两个事务,ide是主键,B 插入了一条id=10的数据,提交了 。A :select * from b where id=10; 结果为null,发现没有id=10的数据,他就插入一条id=10数据,发现insert不进去,说主键重复。A又select一次,发现还是没有id=10的数据,可就是insert不进去,就和幽灵一样,所以称为幻读
脏读,不可重复读的区别。不可重复读只有在其他事务提交了,多次select的状态才会改变。
幻读,不可重复读,针对的都是另一方已经提交的事务,不可重复读,对其他已经提交的事务,select会发现和上次不一样。而幻读select都是一样。不过如果别人新增了id=10,他虽然select没有看到,但就是insert不进去。
下面是来自CSDN的一张图:https://blog.csdn.net/dengjili/article/details/82468576
锁
事务不等于锁,事务的保证是靠 undo log+策略(隔离级别),为了保证策略的完成才加锁的, 持久化是靠redo log
按占用方式分
无锁:不加锁
共享锁:select * from b lock in share mode;8.0之前 S lock:只能读不能写
排它锁:增删改默认排它锁,select * from xx for update X lock:只有获取锁的事务才能操作
按锁的粒度分
行级锁 :select搜索条件例如where子句中必须包含索引列。
record lock(普通行级锁)
gap lock(间隙锁)
表级锁 :select * from b where username='kk' for update 前提是你for update自己加锁。搜索条件没有索引列继而需要全盘扫描 就是表级锁
锁升级:
如果事务A:select * from b where id=10 for update;普通行锁id是索引。
事务B:select * from b where name="kk" for update;name不是索引,索引这里需要全盘扫描,表锁。
事务A 本来是行级锁,为了让A事务中那条sql不受B的干扰,会将A那条sql涉及到的表直接升为表级锁,这样B事务就不会干扰A事务那条操作了
- 持久性(durability)
一旦数据提交,这些数据就会永久的保存在数据库中(你删了不算),即使断电,mysql宕机,再重启后他也会将数据恢复。