1、首先查看mysql 的autocommit设置,默认是自动提交
show VARIABLES LIKE 'autocommit';
修改方法,修改mysql配置文件,设置如下 0代表关闭自动提交, 1代表开启自动提交
autocommit=0
重启mysql。
MySQL 在自动提交模式下,每个增删改的 SQL 语句都是一个独立的事务。
mysql的autocommit(自动提交)默认是开启,其对mysql的性能有一定影响,举个例子来说,如果你插入了1000条数据,mysql会commit1000次的,如果我们把autocommit关闭掉,通过程序来控制,只要一次commit就可以了。
MySQL的autocommit模式默认是打开状态,为了防止手动的DML操作导致失误,生产环境可以设置为默认关闭的状态。一般的jdbc 连接池默认都是开启状态,而且是可配置的。显式事务下会设置成关闭状态,单纯的修改数据库环境的autocommit不会对代码的行为产生影响。
2、事务的四大特性
事务的四大特性ACID(Atomicity原子性、Consistency一致性、Isolation隔离性、Durability持久性),今天就来讲讲其中的隔离性。当数据库上有多个事务同时执行的时候,就可能出现脏读(dirty read)、不可重复读(non-repeatable read)、幻读(phantom read)的问题,为了解决这些问题,就有了事务隔离级别这个概念。
首先你要知道,隔离得越结实,效率就会越低。因此需要我们考虑到这两点,不能只顾一边。SQL的标准事务隔离级别包括:
- 读未提交(read uncommitted):一个事务还没有提交时,它做的变更就能被别的事务看到。
- 读提交(read committed):一个事物提交之后,它做的变更才会被其他事务看到。
- 可重复读(repeatable read):一个事物执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。未提交变更对其他事务也是不可见的。
- 串行化(serializable):对于同一行记录,写会加“写锁”,读会加“读锁”,当出现锁冲突时,后访问的事务需要等前一个事务执行完成,才能继续执行。
其中,“读提交”和“可重复读”比较难理解,这里用一个例子说明一下。
假设数据表中 test 中只有一列,其中一行的值为 1,下面是按照时间顺序执行两个事务的行为。
在不同的隔离级别下,事务A查到的结果是不一样的:
- 若隔离级别是“读未提交”,则 v1 的值是2,这时候事务 B 虽然还没有提交,但是结果已经被事务 A 看到了,因此 v2、v3 也都是2。
- 若隔离级别是“读提交”,则 v1 是1,v2 的值是 2 ,事务 B 的更新在提交后才被事务 A 看到。所以 v3 的值也是 2。
- 若隔离级别是“可重复读”,则 v1、v2是 1,v3 是2,之所以 v2 还是1,遵循的就是这个要求:事务在执行期间看到的数据前后必须是一致的。
- 若隔离级别是“串行化”,则在事务 B 执行“将 1 改成 2”的时候,会被锁住,直到事务 A 提交后,事务 B 才可以继续执行,所以从事务 A 的角度看,v1、v2的值是1,v3的值是2。
可使用以下语句查看mysql的事务的隔离级别
show variables like 'transaction_isolation';
结果:
READ-COMMITTED
修改方法:修改mysql配置文件
transaction_isolation=READ-COMMITTED
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
READ UNCOMMITTED | 可能 | 可能 | 可能 |
READ COMMITTED | 不可能 | 可能 | 可能 |
REPEATABLE READ | 不可能 | 不可能 | 可能 |
SERIALIZABLE | 不可能 | 不可能 | 不可能 |
脏读
脏读是指一个事务正在访问数据,并且对数据进行了修改,但是这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
不可重复读
不可重复读是指在一个事务内,多次读取同一个数据。在这个事务还没有结束时,另外一个事务也访问了该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
幻读
幻读是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。