`
wangleide414
  • 浏览: 590633 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

django mysql 查询不出数据表中的新数据(数据库事务)

 
阅读更多


 背景:实际django项目中遇到这样一个问题,两个进程A,B去读写MySQL数据库,A 在insert m 完成后通过redis 通知B去读MySQL。如下图所示,在进程B允许过程中,往数据库多插入几十条数据后,进程B依然查询不到。如下图所示:实际数据表中有6250,但是在进程中查询只有6218条,他对进程启动动新增的数据都查询不到。

              

                                               

 

 

问题:A insert完成后,这时B并不能查询到新增的记录m。但是通过其他客户端工具可以看到新增的m记录,特别的是B进程在重启后也能看到记录m。

          当然更有意思的是这种现象在开发环境中并不会出现,只在测试环境中会有该问题。

 

 

分析1:由于项目使用的django技术,对MySQL查询和插入操作也是django封装进行,加上数据库确实存在该记录。所以怀疑是django没有去真实查询数据库。

 

排查过程1:到底有没有真实去查数据库?由于该问题是可以复现的,所有使用python manage.py shell 进来一步步去查。

              第一,tcpdump 抓包可以搞定,第二,如果是测试开发环境,可以把MySQL 查询日志 的打开,通过日志去看是否进行查询动作。

             这里使用方法1,在进程B的机器上执行 tcpdump port 3306, 如果想通过wireshrk 查看详细信息可以使用:tcpdump -w  mysql.pcap port 3306 and host xxx ,打开

             mysql.pcap就能看确实进行了查询,如图一:

 

 

           

分析2:看来B是去查询MySQL了。但是MySQL确实没有返回m,看来是django 使用MySQL有些配置上有问题(不要轻易怀疑是MySQL的问题,毕竟它很成熟,一般都是使用上的不当)。这次为了证明这个猜想,需要打开MySQL的日志了。

 

排查过程2:找到my.cnf  在[mysqld] 下增加 log=/var/log/mysql/mysql.log 的配置。重启msyql(注:该操作仅限于在开发测试环境排查问题用,在生产环境慎用影响性能)

            然后我们用tail -f /var/log/mysql/mysql.log 来观察 A 和 B 到底在干嘛。如图二:

           

       通过查询日志可以知道的是,数据确实保存到了数据库中,其他客户端也可以查出。但是进程B查不出,并且B在开始时设置了set autocommit=0表示要手动提交事务。由于数据库的事务隔离

       级别的不同会导致两个事务查询出不同的结果。关于事务隔离级别的话在另一篇文章中有详细的介绍。

       

       可以通过下边的语句来看数据库的隔离级别是什么。当然操作具体表时还需要看表的引擎,比如MyISAM 是不支持事务的,而InnoDB是支持事务的。也就是说不管你的事务隔离机制如何,             MyISAM 类型的表都可以立即查询到已经真实存储在数据库中的记录。

select @@TX_ISOLATION;

 

 

解决方法:

    找到了原因解决方法就方便多了。

(1)如果觉得没有必要用事务,也就是每条语句执行后就可以直接持久化到数据,那就把django 中的 ‘django.middleware.transaction.TransactionMiddleware’去掉

(2)光是查询的话可以使用下边的代码:

from django.db import transaction
with transaction.autocommit():
      #业务代码

(3)第三个就是修改数据库的事务隔离级别(一般不建议)

(4)修改表的数据引擎,刚开始背景中介绍的开发环境不存在,测试环境存在,原因就是表引擎不同。

 

总结:

 

遇到问题后,首先要冷静分析现象出现的场景。什么情况下会复现该问题。尽量能使用差异点来定位问题可能的原因。

 

就像上边这个现象,B在重启后可以查询到m。利用其它客户端也能查询到m,唯独在B运行过程中查询不到,就可以根据B运行中和B重启的差异来分析。

 

当然如果对数据库事务熟悉的同学应该会敏感的想到可能的原因。也就不用去看msyql  log 了。

  • 大小: 13.2 KB
  • 大小: 5.9 KB
  • 大小: 42 KB
  • 大小: 18 KB
  • 大小: 3.8 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics