事务:一组操作要么全部成功,要么全部失败,目的是为了保证数据一致性
原子性:当前事务的操作要么同时成功,要么同时失败。原子性由undo log日志来实现
一致性:使用事务的最终目的,由其他三个特性以及业务代码正确逻辑来实现
隔离性:在事务并发执行时,他们内部的操作不能互相干扰,隔离性由MySQL的各种锁以及MVCC机制来实现
持久性:一旦提交了事务,它对数据库的改变就应该是永久性的。持久性由redo log日志来实现
读未提交:会出现脏读 即 事务A读到了事务B已经修改但尚未提交的数据
读已提交:会出现不可重复读 即 事务A内部的相同查询语句在不同时刻读出的结果不一致
可重复读:会出现幻读 即 事务A读取到了事务B提交的新增数据(不管其他线程怎么修改数据,在当前事务中查询到的数据都是最早之前的数据即快照且不会改变)
串行:解决上面所有问题,包括脏写
脏写: 当两个或多个事务选择同一行数据修改,有可能发生更新丢失问题,即最后的更新覆盖了由其他事务所做的更新
Select操作是快照读(历史数据)
insert、update、delete是当前读(当前数据)
读已提交,语句级快照
可重复读,事务级快照
读锁:select …. lock in share mode
共享锁,读锁是共享的,多个事务可以同时读取同一个资源,但不允许其他事务修改
写锁:
排他锁,写锁是排他的,会阻塞其他的写锁和读锁,update、delete、insert都会加锁
隔离级别是串行的话,执行读操作会加上读锁,读锁和写锁是互斥的
在每个读操作上加上读锁
需要看事务隔离级别和业务需求
如果有多条select查询语句,在rr可重复读隔离级别下,与其他隔离级别查询到的数据可能是不相等的,需要在读操作上也加事务
rr可重复读的数据都是同一时间维度的,在其他隔离级别如RC读已提交是不需要使用事务的
是否同一时间维度 选择 rr 可重复读
对并发要求高的话 选择 rc 读已提交
Redo日志在后台就一个,十个sql去执行,每个sql针对的表都不一样,redo日志事先在内存中开辟空间,写redo日志的时候是在文件当中按照顺序写
磁盘文件不能顺序写,因为不同的表有不同的ibd文件,这十张表可能落在磁盘的不同地方
1、在RR隔离级别下,将查询等数据准备操作放到事务外
2、事务中避免远程调用,远程调用要设置超时,防止事务等待时间太久
3、事务中避免一次性处理太多数据,可以拆分成多个事务分次处理
4、更新等涉及加锁的操作尽可能放在事务靠后的位置
5、能异步处理的尽量异步处理
6、应用侧(业务代码)保证数据一致性,非事务执行