Я радостно объявляю, что мы меняем все драйверы MongoDB от 10gen для «безопасной записи» по умолчанию. В процессе мы переименовываем все классы соединений в MongoClient, поэтому все драйверы теперь используют один и тот же термин для центрального класса.
PyMongo 2,4, выпущенные сегодня, имеет новые классы , называемые MongoClient
и MongoReplicaSetClient
которые имеют новую настройку по умолчанию, а также новый API для настройки записи-подтверждения под названием «относится запись». Старые Connection
и ReplicaSetConnection
классы PyMongo остаются нетронутыми для обратной совместимости, но теперь они считаются устаревшими и исчезнут в некоторых будущих выпусках. Изменения были внесены сопровождающим PyMongo (и моим любимым коллегой) Берни Хакеттом.
Содержание:
- Фон
- Новые значения по умолчанию
- Пишите проблемы
- auto_start_request
- Как насчет двигателя?
- Вдохновляющий вывод
Фон
Записи MongoDB происходят в два этапа. Сначала водитель направляет серверу insert
, update
или remove
сообщение. Сервер MongoDB выполняет операцию и отмечает результат: он записывает была ли ошибка, сколько документов были обновлены или удалены, и является ли upsert в результате обновления или вставки.
На следующем этапе драйвер запускает getLastError
команду на сервере и ожидает ответа:
Этот getLastError
вызов может быть опущен для скорости, и в этом случае драйвер просто отправляет все свои сообщения записи, не ожидая подтверждения. Режим «запусти и забудь», очевидно, очень высокопроизводительный, поскольку он может использовать преимущества пропускной способности сети без влияния ее задержки . Но этот режим не сообщает об ошибках вашему приложению и не гарантирует, что запись завершена до того, как вы сделаете запрос. Это неправильный режим для использования по умолчанию, поэтому мы меняем его сейчас.
В прошлом мы не были особенно последовательны в наших терминах для этих режимов, иногда говоря о «безопасных» и «небезопасных» записях, в других случаях «блокирующих» и «неблокирующих» и т. Д. Теперь мы находимся пытаясь придерживаться «признанного» и «неподтвержденного», поскольку это лежит в основе разницы. Я буду придерживаться этих условий здесь.
(В древней истории 10gen, до моего времени, планировалось создать полный стек «платформа как услуга» с MongoDB в качестве слоя данных. Тогда имело смысл getLastError
быть отдельной операцией, которая выполнялась явно, и не вызов getLastError
по умолчанию автоматически, но MongoDB — это отдельный продукт, и ясно, что значение по умолчанию необходимо изменить.)
Новые значения по умолчанию
В более ранних версиях PyMongo вы могли создать соединение следующим образом:
from pymongo import Connection connection = Connection('localhost', 27017)
По умолчанию Connection
делал неподтвержденные записи. Вы можете изменить его с помощью safe
опции:
connection = Connection('localhost', 27017, safe=True)
Connection
не изменился в PyMongo 2.4, но мы добавили MongoClient
по умолчанию подтвержденные записи:
from pymongo import MongoClient client = MongoClient('localhost', 27017)
Точно так же ReplicaSetConnection
является устаревшим и преемником MongoReplicaSetClient
. Вы можете получить старое поведение неподтвержденных записей с новыми классами, используя w
опцию:
client = MongoClient('localhost', 27017, w=0)
w=0
это новый способ сказать safe=False
.
w=1
это новый, safe=True
и теперь это по умолчанию. Другие варианты , как j=True
ждать журнала фиксации , или w=2
чтобы ждать репликации , работают так же , как и раньше. Вы все еще можете установить параметры для каждой операции:
client.db.collection.insert({'foo': 'bar'}, w=1)
Пишите проблемы
Старый Connection
класс позволял вам установить для safe
атрибута значение True
or False
или вызвать set_lasterror_options()
более сложную конфигурацию. Они устарели, и теперь вы должны использовать MongoClient.write_concern
атрибут. write_concern
является ДИКТ, ключи могут включать в себя w
, wtimeout
, j
и fsync
:
>>> client = MongoClient() >>> # default empty dict means "w=1" >>> client.write_concern {} >>> client.write_concern = {'w': 2, 'wtimeout': 1000} >>> client.write_concern {'wtimeout': 1000, 'w': 2} >>> client.write_concern['j'] = True >>> client.write_concern {'wtimeout': 1000, 'j': True, 'w': 2} >>> client.write_concern['w'] = 0 # disable write acknowledgement
Вы можете видеть, что по умолчанию write_concern
используется пустой словарь. Это эквивалентно w=1
значению «делать регулярные подтвержденные записи».
auto_start_request
Это очень занудно, но мой личный фаворит. Значение по умолчанию для auto_start_request
изменяется с True
на False
.
Краткое объяснение таково: со старым Connection
вы можете записать некоторые данные на сервер без подтверждения, а затем сразу же прочитать эти данные обратно, при условии, что не было ошибки и что вы использовали один и тот же сокет для записи и чтения. , Если вы использовали разные сокеты для этих двух операций, то не было никакой гарантии «прочитайте вашу последовательность записи», потому что запись все еще могла быть поставлена в очередь на одном сокете, в то время как вы завершили чтение на другой.
Вы можете прикрепить текущий поток к одному сокету Connection.start_request()
, и фактически по умолчанию для Connection
каждого запроса вы запускаете запрос для вас. Это auto_start_request
. Он предлагает некоторые гарантии согласованности, но требует, чтобы водитель открыл дополнительные розетки.
Теперь то, что MongoClient
ждет подтверждения каждой записи, auto_start_request
больше не нужно. Если вы делаете это:
>>> collection = MongoClient().db.collection >>> collection.insert({'foo': 'bar'}) >>> print collection.find_one({'foo': 'bar'})
… тогда find_one
он не будет работать до тех пор, пока не insert
будет подтвержден, что означает, что ваш документ определенно был вставлен, и вы можете уверенно запрашивать его в любом сокете. Мы отключили auto_start_request
для повышения производительности и меньше сокетов. Если вы делаете неподтвержденные записи с w=0
последующими чтениями, вам следует подумать, следует ли вам звонить MongoClient.start_request()
. Подробности (с диаграммами!) Смотрите в моем блоге на запросы от апреля.
миграция
Connection
и ReplicaSetConnection
останется на некоторое время (не навсегда), поэтому ваш существующий код будет работать так же, и у вас будет время для миграции. Мы работаем над обновлением всей документации и примера кода для использования новых классов. Со временем мы добавим предупреждения об устаревании к старым классам и методам перед их полным удалением.
Если вы поддерживаете библиотеку, построенную на PyMongo, вы можете проверить наличие новых классов с помощью следующего кода:
try: from pymongo import MongoClient has_mongo_client = True except ImportError: has_mongo_client = False
Как насчет двигателя?
Мотор в бета-версии, поэтому я буду беспощадно нарушать обратную совместимость ради чистоты. В течение следующей недели или двух я объединю официальные изменения PyMongo с моим форком , и я разберусь с ядерными символами MotorConnection
и MotorReplicaSetConnection
, чтобы заменить их на MotorClient
и MotorReplicaSetClient
.
Вдохновляющий вывод
Некоторое время мы знали, что неподтвержденные записи были неправильным значением по умолчанию. Теперь пришло время исправить это. Новый MongoClient
класс позволяет вам переходить от старого по умолчанию к новому на досуге и приносит бонус: все водители соглашаются с названием главной точки входа. Для программистов, плохо знакомых с MongoDB, включение подтверждения записи по умолчанию является огромным преимуществом и делает его намного более интуитивно понятным при написании приложений на MongoDB.