很多人认为MySQL只读事务没啥用,有点鸡肋,以前我也这么认为,自从认真研究了事务的隔离级别和事务的并发问题后,发现这个只读事务其实并不是大家想象的那么无用。下面举一个实际开发中可能会遇到的例子来说明只读事务的作用。
展示用户列表的需求,后台从数据库查询用户列表返回给前端分页显示,分页通过数据库的分页功能实现,前端分页插件需要后台返回总共有多少条记录,以便渲染分页效果,后端返回的数据大概长这样:
{
total:8, // 总共多少条记录
list: [...] // 只包含当前页的记录
}
所以后台需要查询两次数据库:查询总数和查询列表。(有人会说,就不能全部查询出来再在代码里通过sublist分页吗?我这个例子里只有8条数据,万一有80万条数据呢,全部加载到内存不怕内存溢出吗?)
假设我先查询总数返回的是8条,然后在我查询列表前别的事务往数据表中插入了一条数据并commit了,结果我查询列表得到了9条数据。接着就在页面看到了神奇的一幕:总共8条数据,按照每页显示10条来分页,结果第一页有9条数据,这不是有毛病么?
是的,上述情景就是典型的不可重复读问题。我们都知道有个事务隔离级别叫“REPEATABLE READ”,此隔离级别可以实现可重复读,但是别忘了事务的隔离级别前提是要有事务啊,两个查询语句都没有处于事务中,还谈啥事务的隔离级别啊?还谈啥可重复读啊?这个我还真做过实验,就算事务的隔离级别是可重复读级别,两个查询语句没有处于事务中时,还是会出现不可重复读问题。
所以在REPEATABLE READ隔离级别下需要结合事务才能实现可重复读,而只读事务比读写事务更高效,因为不需要写数据,所以做了一些优化。没错,只读事务就是这么来的。
还有人说只读事务不能进行写操作,这确实没错,但我认为不能写是结果而不是目的。