详细了解mysql的事物

详细了解mysql的事物

数据库事务(Database Transaction),是指作为单个逻辑工作单元执行的一系列操作,要么完全执行,要么完全地不执行。

原子性(Atomicity)

一个事物被视为不可分割的最小工作单元,整个事务中所有操作要么全部提交成功,要么全部失败回滚。不可能只执行其中的一部分操作。

一致性(Consistency)

一致性是指事务必须使数据库从一个一致的状态变到另外一个一致的状态,也就是执行事务之前和之后的状态都必须处于一致的状态。

隔离性(Isolation)

隔离性通常来说,一个事务所做的修改在提交之前,对其他事务是不可见的。

持久性(Durability)

持久性是指一个事务一旦被提交了,那么对于数据库中的数据改变就是永久性的,即便是在数据库系统遭遇到故障的情况下也不会丢失提交事务的操作。

MySQL默认采用自动提交(autocommit )模式,当然可以修改启用或者禁用自动修改模式,可以通过set autocommit = 0设置禁止自动提交。

这里重点说下mysql事物的隔离性

MySQL InnoDB事务的隔离级别有四级,默认是“可重复读”(REPEATABLE READ)。

1.未提交读(READ UNCOMMITTED)。另一个事务修改了数据,但尚未提交,而本事务中的SELECT会读到这些未被提交的数据(脏读)一般很少用不推荐。

2.提交读(READ COMMITTED)。本事务读取到的是最新的数据(其他事务提交后的)。问题是,在同一个事务里,前后两次相同的SELECT会读到不同的结果(不重复读)。

3.可重复读(REPEATABLE READ)。在同一个事务里,SELECT的结果是事务开始时时间点的状态,因此,同样的SELECT操作读到的结果会是一致的。会出现幻读现象。

4.串行化(SERIALIZABLE)。读操作会隐式获取共享锁,可以保证不同事务间的互斥,最安全但是性能最低

这里面的问题:

脏读,另一个事务修改了数据,但尚未提交,而本事务中的SELECT会读到这些未被提交的数据。

不重复读。同一个事务执行过程中,另外一个事务提交了新数据,因此本事务先后两次读到的数据结果会不一致。

幻读。保证了同一个事务里,查询的结果都是事务开始时的状态(一致性)。但是,如果另一个事务同时提交了新数据,本事务再更新时,则会发现了这些新数据,让人感觉之前的读取的数据有问题

在mysql事物里,隔离级别越高,安全性越好,比如SERIALIZABLE级别,它通过强制事务排序,在每个读的数据行上加上共享锁。可能导致大量的超时现象和锁竞争,所以mysql默认使用REPEATABLE READ不重复读

mysql中引入了mvcc机制解决了SELECT中幻读的问题,但是在insert/update中仍然会出现幻读,具体出现的场景类似于git上多用户提交冲突的问题。这时候在REPEATABLE READ又引入了第二个机制:

Next-Key Lock

InnoDB有三种行锁:

1.Record Lock:单个行记录上的锁

2.Gap Lock:间隙锁,锁定一个范围,但不包括记录本身。GAP锁的目的,是为了防止同一事务的两次当前读,出现幻读的情况

3.Next-Key Lock:前两个锁的加和,锁定一个范围,并且锁定记录本身。对于行的查询,都是采用该方法,主要目的是解决幻读的问题

InnoDb在REPEATABLE-READ下提供Next-Key Lock机制,但是需要业务自己去加锁,如果不加锁,只是简单的SELECT查询,是无法限制并行事务的插入的,也就没有解决幻读现象。