
事务隔离级别(设置完 事务隔离级别,才开启事务)
- 脏读:事务A修改,事务B读取,但事务A失败回滚。事务B读取的修改的值,不是正真的值。(行。某一行数据)
- 不可重复读:事务A读取数据,事务B修改数据并提交了,事务A再次读取,发现两者不一样。(行。update或者delete操作)
- 幻读:事务A修改或查询表某一条件的所有数据,事务B或进行修改或删除操作并提交了,事务A再次查询数据,发现数据还有为修改或者多出写数据等问题。(表)
排它锁(x锁)与共享锁(s锁)
- 添加排它锁:对数据进行操作(update,insert,delete)时,不允许其他事务对同一资源操作(包括读)。事务A对某数据加排它(可读可写),其他事务不能对该数据添加任何锁,不能进行读写。
- 添加共享锁:只能进行读操作,不允许其他操作,只许读。事务A对该数据加共享锁,(锁未释放时)其他事务自能对该数据进行读,不能更改或删除。
- 考虑问题时:这个锁什么时候释放?
read-commited:解决了脏读。
- 方法——–修改 行数据 添加排它锁,提交了事务才释放;
读取 行数据 添加共享锁,读取完就释放。
- 方法——–修改 行数据 添加排它锁,提交了事务才释放;
repeatable-read:解决了脏读,不可重复读。(默认)
- 方法——–修改 行数据 添加排它锁,提交了事务才释放;
读取 行数据 添加共享锁,提交了事务才释放。
- 方法——–修改 行数据 添加排它锁,提交了事务才释放;
serializable:解决了所有问题
- 方法——-对于表来说,读时加s锁,写时加x锁。
总结:
- 数据库并发问题,主要通过设置事务隔离级别来解决,而事务隔离级别一般则通过锁机制的实现;
MySQL默认隔离级别(RR)使用MVCC+锁混合的模式来解决脏读、不可重读、幻读等问题。 - MySQL(Innodb引擎)下
- 默认的事务级别为:可重复读级别(RR);(可通过设置进行更改)
- 默认锁级别为:行锁;(可通过设置进行更改)
- Where筛选条件中使用索引字段的,加的是行锁;不是使用索引字段筛选的,加的是表锁。
意向共享锁和意向排它锁是数据库主动加的,不需要我们手动处理; - 对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁;
- 对于普通SELECT语句,InnoDB不会加任何锁;(可以自己手动上锁)
其他:
乐观锁适用于写比较少的情况下(并发量大/多读场景),即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果是多写的情况,一般会经常产生冲突,这就会导致上层应用会不断的进行retry,这样反倒是降低了性能,所以一般多写的场景下用悲观锁就比较合适。