Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

解决MySQL在线查询超时后,查询会话没有主动关闭的问题 #302

Merged
merged 2 commits into from
Jun 30, 2019

Conversation

hhyo
Copy link
Owner

@hhyo hhyo commented Jun 30, 2019

关联PR:#125

采取原PR中的第二种实现

  • engine类增加thread_id属性,表示当前会话的线程id
  • engine类增加kill_connection的方法用于终止数据库连接
  • query.py增加kill_query_conn的方法调用kill_connection用于终止查询连接
  • 在查询前按照max_execution_time配置增加一个定时终止语句的schedule,查询结束后删除

弊端:

  • 查询又回归最初的同步查询,不依赖django_q,因为django_q序列化所使用的pickle方法不支持Connection对象,无法在获取conn后提交异步task,会抛出如下错误
    TypeError: can't pickle Connection objects
    
  • 各类数据库kill_connection后的错误不一致,无法try Exception后给出友好的查询终止提示,MySQL查询会话在被终止后会抛出
    (2013, 'Lost connection to MySQL server during query')
    
  • django_q轮询间隔为30s,所以终止会话的操作会有30s的误差

但是问题是解决了,各类数据库拓展对应的方法也可以实现

@hhyo hhyo requested review from LeoQuote and kjiLupin June 30, 2019 04:43
@codecov
Copy link

codecov bot commented Jun 30, 2019

Codecov Report

Merging #302 into master will decrease coverage by <.01%.
The diff coverage is 85.07%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #302      +/-   ##
==========================================
- Coverage   85.06%   85.05%   -0.01%     
==========================================
  Files          66       66              
  Lines        8630     8658      +28     
==========================================
+ Hits         7341     7364      +23     
- Misses       1289     1294       +5
Impacted Files Coverage Δ
sql/engines/mysql.py 90.47% <100%> (+0.2%) ⬆️
sql/engines/tests.py 99.77% <100%> (ø) ⬆️
sql/utils/tasks.py 91.66% <100%> (+1.19%) ⬆️
sql/tests.py 100% <100%> (ø) ⬆️
sql/engines/__init__.py 55.55% <62.5%> (+1.01%) ⬆️
sql/query.py 53.28% <73.07%> (+0.97%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update adf2f38...3cfddab. Read the comment docs.

@LeoQuote
Copy link
Collaborator

有没有可能单做一个query函数把engine包一下。这样就没有pickle的问题了

@LeoQuote
Copy link
Collaborator

或者传过去之前把connection 设为 None (这个方法有些dirty

@hhyo
Copy link
Owner Author

hhyo commented Jun 30, 2019

connection设置为None,执行query时会重新get_connection,thread_id就不一致了,最开始貌似redis也是类似的问题#131

@LeoQuote
Copy link
Collaborator

LeoQuote commented Jun 30, 2019

可以有一个人query with timeout的函数,然后在里面getengine,然后query,开始计时,过期后开始杀进程。

要是django-Q原生支持超时也回调函数就好了,超时直接杀死太傻逼了

@hhyo
Copy link
Owner Author

hhyo commented Jun 30, 2019

只杀python的查询进程的话效果应该是一致的,远端的mysql会话依然不会断开

使用task可以保证前端页面关闭后,如果到超时时间还是可以正常杀掉,不过实现确实不优雅,找不到更合适的处理方式

@hhyo hhyo merged commit 78a1863 into master Jun 30, 2019
@hhyo
Copy link
Owner Author

hhyo commented Jun 30, 2019

先合了,后面可以再调整

@chenhaichao04
Copy link

chenhaichao04 commented Jul 2, 2019

在执行sql查询之前可以设置SESSION参数MAX_EXECUTION_TIME与异步task超时时间一致,如cursor.execute('SET SESSION MAX_EXECUTION_TIME=100000;')。达到该时间后mysql中的查询会话如无正常结束会被自动清理掉。

@hhyo
Copy link
Owner Author

hhyo commented Jul 2, 2019

@chenhaichao04 这个最开始考虑过,不过参数是5.7.8才引入的,不能完全通用,就不在采用范围内

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants