以下文章来源于何先振,责编小何

上节我们介绍了事务的隔离级别,MySQL默认的数据库隔离级别是可重复读。
可以通过命令查看。
select @@transaction_isolation;

现在我们使用cmd命令窗口登录root用户。

输入密码登录成功,使用root用户代表一个事务操作。

再创建一个用户。

登录刚刚创建的用户hexz,模拟另外一个事务。


使用root用户查看,现在的数据库有这么多个。

但是hexz用户下,查看数据库只有一个。需要开通权限。

使用root给hexz用户授权,开通hexz_jdbc数据库所有表的增删改查权限。

这个时候再使用hexz用户查,就可以查到hexz_jdbc数据库了。

我们使用root用户查询hexz_jdbc数据库的user_table表的张三用户,查看账户是900元。

然后分别在root和hexz用户下,开启手动提交事务,模拟两个事务并发执行。


root用户的事务把张三这条数据改成了2000,但是还没有提交。

因为MySQL默认的事务隔离级别是可重复读,使用hexz用户的事务查看张三的数据,还是原来的900元,避免了脏读。

这个时候root用户的事务提交了。

hexz用户的事务,继续查还是原来的900元。解决了不可重复读的问题。不可重复读就是一个事务读取同一个字段多次,会出现数据不一致。

怎么样才能读到root用户的事务修改的值呢,需要提交hexz用户的事务。

然后重新开启一个事务,读到的是最新的值。

现在我们不使用默认的隔离级别,改成读已提交,再来演示下。使用如下命令修改数据库的隔离级别为读已提交。
set global transaction isolation level read committed;

改完之后,root和hexz用户重新登录,查询现在的隔离级别,此时变成读已提交。


再分别开启手动提交事务


使用root用户开启一个事务查看张三用户金额为2000元。

使用hexz用户开启一个事务查询张三金额也是2000元。

此时两个事务都还没提交,使用root的事务修改金额为4000元。

使用hexz事务查张三,还是2000元。因为数据库的隔离级别是读已提交,root事务修改了4000还没有提交。

现在提交root事务

这次在查hexz的事务,就是4000元了。因为root事务已经提交了,隔离级别是读已提交。这会导致一个事务里数据不可重复读问题。

现在修改成读未提交。
set global transaction isolation level read uncommitted;

root和hexz重新登录,查看隔离级别,都是读未提交。


root和hexz用户分别开启手动提交事务


分别使用root和hexz用户开启一个事务,查询张三的金额都是4000元。


此时两个事务还没有提交,接着事务root用户修改金额为8000元。

此时root事务还没提交,然后hexz用户的事务再次查询张三的金额变成了8000元。

这是因为我们设置的数据库隔离级别为读未提交,所以root修改了数据就算没有提交,也可以读出来。
这个时候root回滚数据。

hexz再次读取,就会变成4000元,上面读出的8000元就是脏读数据。

使用JDBC查询张三这条数据,可以通过连接对象获取当前的隔离级别。

控制台输出为1

进入Connection接口,ctrl+F12显示类的结构,可以看到1就是读未提交。


此时查出来的张三金额为4000元。代码开启了手动提交事务,并且还没有提交事务。

再编写一个修改张三账户金额为3000元的方法,这个方法手动开启了事务,修改完事务会暂停15秒。

执行修改事务的方法,修改完后事务暂停15秒。

执行查询事务,此时由于隔离级别是读未提交,所以可以把修改事务中未提交的数据3000元查出来,出现了脏写。

后面修改事务执行完,由于没有提交事务,没有正式生效。

继续执行查询事务,还是4000元。

可以通过JDBC将数据库隔离级别修改为读已提交。


此时执行修改事务时,修改成3000元会暂停15秒。


同时执行查询事务,就不会读到修改事务中未提交的数据,还是4000元。


如果要恢复,默认的数据库隔离级别,可以重启下数据库服务。

重启后恢复成可重复读。


扫码进微信答疑群





