国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|數據庫技術|

服務器之家 - 數據庫 - MongoDB - MongoDB游標超時問題的4種解決方法

MongoDB游標超時問題的4種解決方法

2020-05-25 15:54青南 MongoDB

這篇文章主要給大家介紹了關于MongoDB游標超時問題的4種解決方法,文中通過示例代碼介紹的非常詳細,對大家學習或者使用MongoDB具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧

當我們使用Python從MongoDB里面讀取數據時,可能會這樣寫代碼:

?
1
2
3
4
5
6
import pymongo
 
handler = pymongo.MongoClient().db.col
 
for row in handler.find():
 parse_data(row)

短短4行代碼,讀取MongoDB里面的每一行數據,然后傳入parse_data做處理。處理完成以后再讀取下一行。邏輯清晰而簡單,能有什么問題?只要parse_data(row)不報錯,這一段代碼就完美無缺。

但事實并非這樣。

你的代碼可能會在for row in handler.find()這一行報錯。它的原因,說來話長。

要解釋這個問題,我們首先就需要知道,handler.find()返回的并不是數據庫里面的數據,而是一個游標(cursor)對象。如下圖所示:

MongoDB游標超時問題的4種解決方法

只有當你使用for循環開始迭代它的時候,游標才會真正去數據庫里面讀取數據。

但是,如果每一次循環都連接數據庫,那么網絡連接會浪費大量時間。

所以pymongo會一次性獲取100行,for row in handler.find()循環第一次的時候,它會連上MongoDB,讀取一百條數據,緩存到內存中。于是第2-100次循環,數據都是直接從內存里面獲取,不會再連接數據庫。

當循環進行到底101次的時候,再一次連接數據庫,再讀取第101-200行內容……

這個邏輯非常有效地降低了網絡I/O耗時。

但是,MongoDB默認游標的超時時間是10分鐘。10分鐘之內,必需再次連接MongoDB讀取內容刷新游標時間,否則,就會導

致游標超時報錯:

pymongo.errors.CursorNotFound: cursor id 211526444773 not found

如下圖所示:

MongoDB游標超時問題的4種解決方法

所以,回到最開始的代碼中來,如果parse_data每次執行的時間超過6秒鐘,那么它執行100次的時間就會超過10分鐘。此時,當程序想讀取第101行數據的時候,程序就會報錯。

為了解決這個問題,我們有4種辦法:

  1. 修改MongoDB的配置,延長游標超時時間,并重啟MongoDB。由于生產環境的MongoDB不能隨便重啟,所以這個方案雖然有用,但是排除。
  2. 一次性把數據全部讀取下來,再做處理:
?
1
2
3
4
all_data = [row for row in handler.find()]
 
for row in all_data:
 parse(row)

這種方案的弊端也很明顯,如果數據量非常大,你不一定能全部放到內存里面。即使能夠全部放到內存中,但是列表推導式遍歷了所有數據,緊接著for循環又遍歷一次,浪費時間。

  3.讓游標每次返回的數據小于100條,這樣消費完這一批數據的時間就會小于10分鐘:

?
1
2
3
# 每次連接數據庫,只返回50行數據
for row in handler.find().batch_size(50):
 parse_data(row)

但這種方案會增加數據庫的連接次數,從而增加I/O耗時。

  4.讓游標永不超時。通過設定參數no_cursor_timeout=True,讓游標永不超時:

?
1
2
3
4
cursor = handler.find(no_cursor_timeout=True)
for row in cursor:
 parse_data(row)
cursor.close() # 一定要手動關閉游標

然而這個操作非常危險,因為如果你的Python程序因為某種原因意外停止了,這個游標就再也無法關閉了!除非重啟MongoDB,否則這些游標會一直留在MongoDB上,占用資源。

當然可能有人會說,使用try...except把讀取數據的地方包住,只要拋出了異常,在處理異常的時候關閉游標即可:

?
1
2
3
4
5
6
7
8
cursor = handler.find(no_cursor_timeout=True)
try:
 for row in cursor:
 parse_data(row)
except Exception:
 parse_exception()
finally:
 cursor.close() # 一定要手動關閉游標

其中finally里面的代碼,無論有沒有異常,都會執行。

但這樣寫會讓代碼非常難看。為了解決這個問題,我們可以使用游標的上下文管理器:

?
1
2
3
with handler.find(no_cursor_timeout=True) as cursor:
 for row in cursor:
  parse_data(row)

只要程序退出了with的縮進,游標自動就會關閉。如果程序中途報錯,游標也會關閉。

它的原理可以用下面兩段代碼來解釋:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Test:
 def __init__(self):
  self.x = 1
 
 def echo(self):
  print(self.x)
 
 def __enter__(self):
  print('進入上下文')
  return self
 
 def __exit__(self, *args):
  print('退出上下文')
  
with Test() as t:
 t.echo()
print('退出縮進')

運行效果如下圖所示:

MongoDB游標超時問題的4種解決方法

接下來在with的縮進里面人為制造異常:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Test:
 def __init__(self):
  self.x = 1
 
 def echo(self):
  print(self.x)
 
 def __enter__(self):
  print('進入上下文')
  return self
 
 def __exit__(self, *args):
  print('退出上下文')
  
with Test() as t:
 t.echo()
 1 + 'a' # 這里一定會報錯
print('退出縮進')

運行效果如下圖所示:

MongoDB游標超時問題的4種解決方法

無論在with的縮進里面發生了什么,Test這個類中的__exit__里面的代碼始終都會運行。

我們來看看pymongo的游標對象里面,__exit__是怎么寫的,如下圖所示:

MongoDB游標超時問題的4種解決方法

可以看到,這里正是關閉游標的操作。

因此,如果我們使用上下文管理器,就可以放心大膽地使用no_cursor_timeout=True參數了。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對服務器之家的支持。

原文鏈接:https://juejin.im/post/5d555eb45188255d51425bda

延伸 · 閱讀

精彩推薦
  • MongoDBMongoDB憑什么躋身數據庫排行前五

    MongoDB憑什么躋身數據庫排行前五

    MongoDB以比去年同期超出65.96分的成績繼續雄踞榜單前五,這個增幅在全榜僅次于PostgreSQL的77.99,而其相對于4月份的6.10分的增長也是僅次于微軟SQL Server排名...

    孫浩峰3892020-05-22
  • MongoDBMongodb實現定時備份與恢復的方法教程

    Mongodb實現定時備份與恢復的方法教程

    這篇文章主要給大家介紹了Mongodb實現定時備份與恢復的方法教程,文中通過示例代碼介紹的非常詳細,對大家具有一定的參考學習價值,需要的朋友們下面...

    chenjsh364522020-05-13
  • MongoDBMongoDB安裝圖文教程

    MongoDB安裝圖文教程

    這篇文章主要為大家詳細介紹了MongoDB安裝圖文教程,分為兩大部分為大家介紹下載MongoDB和安裝MongoDB的方法,感興趣的小伙伴們可以參考一下 ...

    Yangyi.He6132020-05-07
  • MongoDB分布式文檔存儲數據庫之MongoDB分片集群的問題

    分布式文檔存儲數據庫之MongoDB分片集群的問題

    這篇文章主要介紹了分布式文檔存儲數據庫之MongoDB分片集群的問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋...

    Linux-18743072020-12-20
  • MongoDBMongoDB 內存使用情況分析

    MongoDB 內存使用情況分析

    都說 MongoDB 是個內存大戶,但是怎么知道它到底用了多少內存呢...

    MongoDB教程網10002020-09-29
  • MongoDBMongoDB中javascript腳本編程簡介和入門實例

    MongoDB中javascript腳本編程簡介和入門實例

    作為一個數據庫,MongoDB有一個很大的優勢——它使用js管理數據庫,所以也能夠使用js腳本進行復雜的管理——這種方法非常靈活 ...

    MongoDB教程網6982020-04-24
  • MongoDB遷移sqlserver數據到MongoDb的方法

    遷移sqlserver數據到MongoDb的方法

    這篇文章主要介紹了遷移sqlserver數據到MongoDb的方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下...

    聽楓xl9682021-01-03
  • MongoDBmongodb基本命令實例小結

    mongodb基本命令實例小結

    這篇文章主要介紹了mongodb基本命令,結合實例形式總結分析了MongoDB數據庫切換、查看、刪除、查詢等基本命令用法與操作注意事項,需要的朋友可以參考下...

    dawn-liu3652020-05-26
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 国产成人一区 | 日韩欧美一区二区三区在线观看 | 久久久91精品国产一区二区三区 | 中文字幕综合 | 中文字幕一区二区三区四区不卡 | 日本电影一区 | 激情五月婷婷 | 久久伊人亚洲 | 爱爱视频网站 | 亚洲电影在线播放 | 午夜资源| 色狠狠久久av五月综合 | 国内精品视频在线观看 | 日韩资源在线 | 午夜视频| 永久免费av| 天堂√在线观看一区二区 | 日本一区二区三区视频免费看 | 欧美va天堂 | 中文天堂在线观看视频 | 久久精品国产一区二区三区 | 日本一区不卡 | 天天澡天天狠天天天做 | 免费一区二区 | 久久777 | 日韩欧美一区二区在线观看视频 | 91xxx在线观看 | 毛片大片 | 91精品国产综合久久香蕉最新版 | 最新国产在线视频 | 91av入口 | 国产精品一区二区三区免费 | 欧美精品一二三 | 日日骚网 | 日韩在线播放一区二区 | 日本中文字幕一区 | 午夜网 | 黄色一级大片免费 | 夜夜操av | 成人a在线视频免费观看 | 国产精品久久影院 |