事务:
4个属性:
- 原子性:事务中包含的程序,要么全部执行,要么完全不执行(做一件事,做就做完,要么就不做)
- 一致性:执行完数据操作后,数据不会被破坏(a用户转给b用户钱,a扣除了多少,b就得加多少)
- 隔离性:每个事务操作的数据不能相互影响。(两个事务修改,查询,同时对一个值操作。,同时开启事务,数据是5,数据先修改成6.完成,提交事务。但是查询事务数据必须是5.不会因为另一个事务对其数据变更,而有变化)
- 持久性:事务完成后,数据的修改是永久性的
并发事务:
- 更新丢失或者脏写:两个事务并发修改一个数据, 数据可能被覆盖,导致数据丢失(a等于5,两个事务进行增加操作。事务一:增加1,事务二:增加2.。如果顺序执行,a的值应该等于8.。发生并发操作可能变成 a等于6或者7。因为事务一和事务二,拿到的a都是5)
- 脏读:事务a读取到了事务b已经修改但为提交的数据(如果事务b回滚,a读取的数据将无效)
- 不可重复读(数据修改):事务开启,但没提交,同一条语句查询两次(期间数据进行修改),得到的结果不同。(在一个事物内)
- 幻读(数据新增):在事务内,a事务读取到了,b事务提交的数据(一个表,三条数据。a事务查询,b事务新增。两个事务同时开启,b事务先完成。a事务查询出了b事务新增的数据。a事务开启时,表内只有三条数据,a事务只能查询出事务开启时表内有多少数据)
隔离级别:
- 读未提交:a事务可以读取到b事务没有提交的数据
- 读已提交:a事务只能读取b事务提交的数据
- 可重复读:a事务只能读取,a事务开启时数据库已经存在的数据(修改的数据读取不到。新增的数据可以读到)
- 可串行化:一个事务开启,其它事务不能进行操作(设置串行化(查询也会进行加锁),一个事务查询一条数据,那么其它事务不能对这条数据进行操作。)
锁:
性能分:乐观锁和悲观锁(读锁和写锁都是悲观锁)
数据库操作:
- 读锁:针对同一分数据,多个读操作同时进行互不影响
- 写锁:当前写操作没有完成前,它会阻断其它写锁和读锁
数据库粒度:
- 表锁:在表上加锁(每次操作锁住整张表。开销小,加锁快;不会出现死锁,粒度大发生锁冲突概率高)
- 行锁:行数据加锁(每次操作锁住一行数据,开销大,加锁慢,会出现死锁,粒度小,并发高,冲突小)
串行化:
打开一个客户端A,并设置当前事务模式为serializable,查询id=1
打开一个客户端A,并设置当前事务模式为serializable,
- 查询id=1,会被阻塞
- 查询或者更新id=2,会被执行
间隙锁:
如果a事务查询是一个范围查询,如果b事务在a的范围内操作数据。那么b就会被阻塞。
临键锁:也是一个范围
无索引行锁,进行查询,会升级表锁
锁优化建议
1:尽可能让所有数据检索都通过索引来完成,避免无索引行锁升级为表锁
2:合理设计索引,尽量缩小锁的范围
3:尽可能减少检索条件范围,避免间隙锁
4:尽量控制事务大小,减少锁定资源量和时间长度,涉及事务加锁的sql尽量放在事务最后执行
5:尽可能低级别事务隔离
参考链接:https://www.cnblogs.com/myseries/p/10748912.html