0
点赞
收藏
分享

微信扫一扫

[Mysql] 网站查询数据不是最新的数据

雨鸣静声 2023-11-25 阅读 56

一、发现问题

近期部署一个内部服务站点,提供一个web界面供查询和展示分析后的数据报表,启动时一段时间内数据查询获取的都是最新值,等待几个小时后,网页查询出来的结果不是最新值,但是数据库中是存在更新的数据记录,不知何故?

二、排查过程

在MySQL中事务的隔离级别有4种类型:

  1. 读未提交(READ UNCOMMITTED)
  2. 读已提交(READ COMMITTED)
  3. 可重复读(REPEATABLE READ)
  4. 序列化(SERIALIZABLE)

MySQL 默认的事务隔离级别是可重复读(REPEATABLE READ),这 4 种隔离级别的说明如下。

1.READ UNCOMMITTED

读未提交,也叫未提交读,该隔离级别的事务可以看到其他事务中未提交的数据。该隔离级别因为可以读取到其他事务中未提交的数据,而未提交的数据可能会发生回滚,因此我们把该级别读取到的数据称之为脏数据,把这个问题称之为脏读。

2.READ COMMITTED

读已提交,也叫提交读,该隔离级别的事务能读取到已经提交事务的数据,因此它不会有脏读问题。但由于在事务的执行中可以读取到其他事务提交的结果,所以在不同时间的相同 SQL 查询中,可能会得到不同的结果,这种现象叫做不可重复读。

3.REPEATABLE READ

可重复读,是 MySQL 的默认事务隔离级别,它能确保同一事务多次查询的结果一致。但也会有新的问题,比如此级别的事务正在执行时,另一个事务成功的插入了某条数据,但因为它每次查询的结果都是一样的,所以会导致查询不到这条数据,自己重复插入时又失败(因为唯一约束的原因)。明明在事务中查询不到这条信息,但自己就是插入不进去,这就叫幻读 (Phantom Read)。

4.SERIALIZABLE

序列化,事务最高隔离级别,它会强制事务排序,使之不会发生冲突,从而解决了脏读、不可重复读和幻读问题,但因为执行效率低,所以真正使用的场景并不多。

因为默认MySQL设置的是REPEATABLE READ,所以存在重复读的情况,为解决此问题,需要采用commit(),原因在于:

MySQL如果直接select,默认是自动commit,但是采用pymysql是默认开启事务(需要手动commit),为了每次都能读取到最新的更新,需要commit,如果需要在事务内重复度,则不需要commit,这与隔离级别有关。

[Mysql] 网站查询数据不是最新的数据_隔离级别

三、解决方案

try:
    cursor.execute("select u_time,ip from u_data where datediff(now(),u_time)<1 order by u_time desc;")

    conn.commit()
except:
    conn.rollback()

举报

相关推荐

0 条评论