1、原子性:事务包含的所有数据库操作要么全部成功,要不全部失败回滚。 undo log(回滚日志)
2、一致性:一个事务执行之前和执行之后都必须处于一致性状态。拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。
3、隔离性: 数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致,好比:消费者购买商品这个事务,是不影响其他消费者购买的。 MVCC(多版本并发控制) 或锁机制来保证
4、持久性: 事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。 redo log (重做日志)
并行事务引发的问题:
脏读:一个事务「读到」了另一个「未提交事务修改过的数据」。
不可重复读:一个事务多次读取同一个数据,出现前后两次读到的数据不一样的情况。
幻读:一个事务内多次查询某个符合查询条件的「记录数量」,出现前后两次查询到的记录数量不一样的情况。
为避免以上问题提出的隔离级别:
- 读未提交(read uncommitted),指一个事务还没提交时,它做的变更就能被其他事务看到;
- 读提交(read committed),指一个事务提交之后,它做的变更才能被其他事务看到;
- 可重复读(repeatable read),指一个事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,MySQL InnoDB 引擎的默认隔离级别;
- 串行化(serializable );会对记录加上读写锁,在多个事务对这条记录进行读写操作时,如果发生了读写冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行;
MySQL的隔离级别是 可重复读,怎么解决幻读:
- 针对快照读(普通 select 语句),是通过 MVCC 方式解决了幻读(产生一个Read View读视图),因为可重复读隔离级别下,事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,即使中途有其他事务插入了一条数据,是查询不出来这条数据的,所以就很好了避免幻读问题。
- 针对当前读( MySQL 里除了普通查询是快照读,其他都是当前读,比如 update、insert、delete,这些语句执行前都会查询最新版本的数据,然后再做进一步的操作。),是通过 next-key lock(记录锁+间隙锁)方式解决了幻读,因为当执行 select ... for update 语句的时候,会加上 next-key lock,如果有其他事务在 next-key lock 锁范围内插入了一条记录,那么这个插入语句就会被阻塞,无法成功插入,所以就很好了避免幻读问题。