问题
1.什么是脏写、脏读、不可重复读、幻读?
- 脏写
当多个事务修改同一行数据,有可能最后的更新覆盖了由其他事务所做的更新。
- 脏读(Dirty Reads)
事务A读取到了事务B已经修改但未提交的数据
- 不可重读(Non-Repeatable Reads)
事务A未提交前,内部相同查询语句在不同时刻读出的结果不一致
- 幻读(Phantom Reads)
事务A读取到了事务B提交的新增数据
2.多个事务对同一批数据增删改查,会导致脏写、脏读、不可重复读、幻读这些问题,如何解决?
3.事务隔离机制、锁机制、MVCC多版本并发控制隔离机制、日志机制如何解决多个事务的并发维问题?
事务及其ACID属性属性
事务是一组操作要么全部成功,要么全部失败
- 原子性 当前事务操作要么全部成功,要么全部失败,由undo log实现
- 一致性 数据的正确性和完整性,由其他3个特性实现
- 隔离性 事务之间内部操作互不干扰,由锁和MVCC机制实现
- 持久性 提交事务后对数据库的改变是永久性的,由内存和redo log实现
事务隔离级别
1.查看当前数据库的事务隔离级别: show variables like 'tx_isolation';
2.设置事务隔离级别:set tx_isolation='REPEATABLE-READ';
3.Mysql默认的事务隔离级别是可重复读
4.用Spring开发程序时,如果不设置隔离级别默认用Mysql设置的隔离级别,如果Spring设置了就用Spring设置的隔离级别
案例分析:
--示例表
CREATE TABLE `account` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`balance` int DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;最近比较忙,案例分析会在放假的时候尽快做补充..
大事务的影响
1.数据库连接池容易被撑爆
2.锁定太多的数据,造成大量的阻塞和锁超时
3.执行时间长,容易造成主从延迟
4.回滚所需要的时间比较长
5.undo log膨胀
6.容易导致死锁
如何查看大事务
#查询执行时间超过1秒的事务
SELECT * FROM information_schema.innodb_trx
WHERE TIME_TO_SEC(timediff(now(), trx_started)) > 1;
#强制结束事务kill trx_mysql_thread_id
事务的优化
1.将查询等数据准备操作放到事务外
2.事务中避免远程调用,远程调用要设置超时,防止事务等待时间太久
3.事务中避免一次性处理太多数据,可以拆分成多个事务分次处理
4.更新等涉及加锁的操作尽可能放在事务靠后的位置
5.能异步处理的尽量异步处理
6.应用侧(业务代码)保证数据一致性,非事务执行