mongodb mysql 事务_让你的mongodb支持事务---升级到mongodb 4.0

mongodb 4.0已经支持副本集级别的事务了,而且现在是稳定版.下一个版本4.2准备支持分片的事物.我因为数据库规模较小,暂时用不到分片的规模,于是就先升级到4.0版本.

提醒: mongo官方建议你不要把事务当救命稻草, 更多的时候要依赖良好的设计模式来减少使用多文档事务的机会,毕竟事务是会影响性能的.

先备份数据库,虽说升级后数据库会保留下来,但为了不要最后演变成删库闹剧.还是老老实实的备份数据库吧

mongodump --host 127.0.0.1:27017 --gzip --db db_name --username your_account --password 'your_password' --authenticationDatabase db_name -o your_bak_path

升级前检查/要求:

版本检查

db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )

设置版本兼容性信息

db.adminCommand( { setFeatureCompatibilityVersion: "3.6" } )

mongodb3.6要求,如果你不满足这个条件(比如你是3.4版本),那么请先升级到3.6的版本.

兼容性检查,取消了一些特性,如果你当前的系统用到了这些特性,恐怕你要一些额外的工作,具体的兼容性检查信息在这里

由于我用的是ubuntu16.04我就用这个系统来演示.

添加mongodb的key

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 9DA31620334BD75D9DCB49F368818C72E52529D4

创建源列表

echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/4.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.0.list

更新apt源

sudo apt-get update

安装mongodb 4.0

注意,安装之前必须先停止mongodb的服务,否则会提示安装成功但仍然是原来的3.6版本

sudo apt-get install -y mongodb-org

也可以这么安装

sudo apt-get install -y mongodb-org=4.0.0 mongodb-org-server=4.0.0 mongodb-org-shell=4.0.0 mongodb-org-mongos=4.0.0 mongodb-org-tools=4.0.0

接下来,让我们测试一下.

事务的限制条件

数据库必须工作在副本集或者分片模式.单机模式是不支持事务的. 这点不是问题,把单机转换为只有一个成员的副本集就好了.另外,如果你的兼容性检查显示的是3.6版本的话也不行.

*兼容性检查命令 *

db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )

事务不向下兼容,必须把兼容性提高到4.0

提升版本兼容性

db.adminCommand( { setFeatureCompatibilityVersion: "4.0" } )

多文档事务执行的时候,不会自动创建命名空间. 也就是说,如果你的collection还未建立的话, 你执行事务的时候会报错.

pymongo.errors.OperationFailure: Cannot create namespace mq_db.t1 in multi-document transaction.

这个问题是我估计是由于事务的实现方式导致的.至于能不能打开自动建表的功能我没找到.这个使用的时候要留心这一点.

驱动和数据库版本要求

如果你出现下面的这样的错误

AttributeError: 'ClientSession' object has no attribute 'start_transaction'

那么很可能是你的数据库或者驱动不满足要求.请保证:

mongodb 数据库至少4.0

pymongo 至少3.7版本

演示代码 python3

import pymongo

user = "your_account" # 数据库用户名

password = "your_password" # 数据库密码

db_name = "your_db" # 库名称

mechanism = "SCRAM-SHA-1" # 加密方式,注意,不同版本的数据库加密方式不同。

"""mongodb配置信息"""

mongodb_setting = {

"host": "server_ip:27017", # 数据库服务器地址

"localThresholdMS": 30, # 本地超时的阈值,默认是15ms,服务器超过此时间没有返回响应将会被排除在可用服务器范围之外

"maxPoolSize": 100, # 最大连接池,默认100,不能设置为0,连接池用尽后,新的请求将被阻塞处于等待状态.

"minPoolSize": 0, # 最小连接池,默认是0.

"waitQueueTimeoutMS": 30000, # 连接池用尽后,等待空闲数据库连接的超时时间,单位毫秒. 不能太小.

"authSource": db_name, # 验证数据库

'authMechanism': mechanism, # 加密

"readPreference": "primaryPreferred", # 读偏好,优先从盘,如果是从盘优先, 那就是读写分离模式

"username": user, # 用户名

"password": password # 密码

}

class DB:

"""自定义单例模式客户端连接池"""

def __new__(cls):

if not hasattr(cls, "instance"):

conns = pymongo.MongoClient(**mongodb_setting)

cls.instance = conns

return cls.instance

def get_client() -> pymongo.MongoClient:

"""

获取一个MongoClient(一般用于生成客户端session执行事物操作)

:return:

"""

mongo_client = DB()

return mongo_client

"""开始测试事务,注意: t1和t2请提前创建,事务不会自己创建collection"""

client = get_client()

t1 = client[db_name]['t1'] # 操作t1表的collection,db_name是你的数据库名,你可以这么写client.db_name.collection_name

t2 = client[db_name]['t2'] # # 操作t2表的collection

with client.start_session(causal_consistency=True) as session:

"""事物必须在session下执行,with保证了session的正常关闭"""

with session.start_transaction():

"""一旦出现异常会自动调用session.abort_transaction()"""

t1.insert_one(document={"name": "jack"}, session=session) # 注意多了session这个参数

k = dict()['name'] # 制造一个错误,你会发现t1和t2的插入都不会成功.

t2.insert_one(document={"name": "jack2"}, session=session)

事务必须运行在一个clientSession的session周期内.嵌套了2个with.这只是个示范,生产环境请自行封装.

顺便说一下,mongodb现在已经支持分片的多文档事物了.

你可能感兴趣的:(mongodb,mysql,事务)