把一组操作封装到一起,成为一个共同的执行单元,可以理解为就是一组SQL语句,此时这个执行单元就可以叫作事务。它是Mysql数据库中提供的重要机制。事务中的操作应该满足以下特性:
- 原子性,一个事务应该是一个不可分割的工作单位,要么全都做了,要么全都没做。
- 一致性,事务执行前后,数据应该处于合法状态。
- 持久性,事务执行完毕之后,数据就被永久修改了,也就是写到磁盘里面 了。哪怕重启计算机,也不会改变。
- 隔离性, 多个事务并发执行时,事务之间互不干扰,本质上就是线程安全。
其中,隔离性是最难理解的一点,隔离性和并发执行本质上是相悖的,因为隔离性越高,代表并发执行的时候每个事务之间的联系就越少,并发程度就越低。减少了效率但是提高了数据的准确性。隔离性越低,代表事务之间的联系就越多,并发程度也就越高。提高了效率但是降低了数据的准确性。
虽然两者是相悖的,但是在不同场景下,对于数据的准确性要求不一样。此时就可以在满足数据准确性的要求下,尽可能地提高效率。这就涉及到事务的隔离级别。
在认识事务隔离级别之前,我们先来看看事务并发执行时会出现的三个问题。
- 脏读,如果事务A和事务B是并发执行的,事务A正在修改数据,还没提交呢,此时事务B就把这个数据读取过去了,但是有可能事务A会在事务B读取后再次对这个数据进行修改。此时就产生了脏读
解决办法:给修改操作加上锁。加锁之后A在修改的时候,B尝试读取的话就会阻塞,一直阻塞到A修改完并且提交之后才可能继续读取。 - 不可重复读,虽然事务A修改数据的操作加锁了,但是事务B在读取的时候,事务A仍然可以进行修改。也就是事务B在读取的时候,两次读取到的结果都不一样。
解决办法:给读操作也加上锁。这样一来事务B只有等事务A修改之后才能读取这个数据,并且读取的时候事务A也不能进行修改。
引入读写锁之后,事务的隔离性就越高了,事务A与事务B之间的联系越来越少,逐渐变为串行执行,并发程度越低了,效率也就越低了,但是换来的是数据的准确性就越高。 - 幻读,事务B在读取这个数据的时候,事务A并不是什么也没有做,在那挂机,而是会去新增一些其他数据或者删除一些其他数据。
解决办法:串行化,让事务B在读取的时候事务A就直接什么都不能做,在那挂机。
Mysql中事务的隔离级别就是对事物并发执行时的隔离性要求具体有多高。事物的隔离级别分为以下四级 :
- read uncommitted:允许读取未提交的数据,也就是允许存在脏读问题。此时的隔离性最低,并发性最高。适用于对数据的可靠性要求不是很高的场景
- read committed:只允许读取已经提交的数据,也就是允许存在不可重复读问题。也就是事物A在修改提交的时候事物B不能进行读取。只能提交之后再读取,但是事物B在读取的时候事物A可以进行修改。
- .repeatable read:这是Mysql的默认隔离级别,也就是读写都加锁,但是可以存在幻读问题。
- serializable:严格串行化执行,此时隔离性最高,并发程度最低。此时就类似于线程中的synchronized关键字。
我们可以在SQL语句中显示指定当前SQL语句使用哪种隔离级别,如果不指定的话,就默认是第三级。