首页 > 其他分享 >odoo手动提交事务问题探索

odoo手动提交事务问题探索

时间:2023-02-17 14:46:49浏览次数:28  
标签:事务 手动 回滚 odoo 提交 sql 数据

背景:

在做项目时,发现数据库中几百条数据的修改时间都是相同的。寻找其中原因,在代码层面为了避免大数据量放在一次修改数据,特意做了分页查询,每一页执行一次更新方法,所有数据放在循环里处理。

理论上就能实现数据的分批处理,更新时调用odoo模型中默认的write方法。

原因:

在循环中加断点,每次执行write方法之后,数据应该被修改,但是数据库中数据并未发生变化,而是等所有数据执行完毕才会统一变化。

其中原因就是单独执行write方法时,只提交了修改命令,但是未提交事务,所以数据库没有发生更新,

在源码中找到提交事务的代码,debug,发现循环过程中并未执行提交,只有在最后返回的时候提交一次事务。就造成了上面说的所有数据的修改时间相同。

问题思考:

如果循环的数据量无论多大,都一次提交,如果其中一条数据发生异常,所有数据都将回滚,这是我们担心的问题。再有,如果数据量百万之巨,那么还是一次提交事务会不会因为数据量太大造成其他问题。

 

起初我的想法很简单,既然write方法不能自动提交事务,那么就手动提交,self.env.cr.commit() 在数据库连接的脚本中,创建的游标执行sql之后都是手动提交事务的,

 

 

果然,加上手动提交事务之后,每次循环结束,都能看到数据库中对应的数据发生了变化。

 

后来在odoo社区发现其中有一篇帖子视手动提交事务为洪水猛兽,因为手动提交事务没办法确保出现问题能准确回滚,也就是没办法保证数据的安全性和准确性。

甚至说出了无论你在哪里看到了self.env.cr.commit() 这行代码,都要删了它!

 

 

他说不能手动提交事务,因为不能保证数据出现问题的回滚,我们还考虑到一点,就是手动提交事务的时候,会不会把其他并行事务的未完成的操作一并提交了。

 

能不能手动提交事务,还要看并行的事务之间是什么隔离级别。

数据库并行事务时,不同的隔离级别会出现不同的读取问题,脏读、幻读、不可重复读。

脏读:事务b读到事务a修改的数据,但是a还未提交事务。

不可重复读:在事务a中运行同一条sql两次,第二次结果是被事务b修改过的数据。

幻读:事务a查询时没有发现数据,事务b插入数据,事务a插入数据发现主键冲突,再次查询扔未查到数据

介绍一下并行事务的四种隔离级别。

read uncommitted 读未提交:一个事务还未提交,变更就能被别的事务看到。   

read commited 读已提交:一个事务提交后,变更才能被别的事务看到。 

repeatable read 可重复读:一个事务执行过程中看到的数据,总是跟这个事务启动时看到的数据一致。

seriallizable 可串行化:读写都会加锁,当读写锁冲突时,后访问的事务必须等前一个事务执行完毕才能执行。

 

odoo采用的是后两种 可重复读和可串行化

 

 

确保事务并行过程中的数据安全。既然事务之间的安全级别高,那在一个事务中的提交只与该事务有关。

 

大事务处理

回到提交事务的问题,查阅资料发现有人对数据库做过大数据量的压力测试,事务提交越频繁效率越低

 

 

但是大事务确实也会带来很多问题。比如锁定太多的数据,造成阻塞和锁超时;回滚时间长;执行时间长容易造成主从延迟。

所以取中间合适的数据量提交事务提升效率同时降低风险。

 

postgresql自动提交事务默认开启状态。

关于postgresql的自动提交事务测试。

 

 

关闭自动提交事务

 

 

 

 

插入数据之后回滚能取消上一步操作,并且使用连接工具看不到数据,说明事务并未提交。

未提交的事务,修改的数据无法让其他事务看到,其实还是未修改成功的状态。

 

 

而Postgresql默认是自动提交的,只不过在pgadmain上执行一条sql语句时,执行完毕就会提交。

而当执行多个sql语句时,只有当全部执行完毕,第一个sql语句才会自动提交。

若第一个sql语句时update语句,sql全部执行完毕后,数据表才会进行update的提交,数据表才会改变,否则,数据表是不会改变的。

连续的sql语句会放在一起执行,也就是作为一个sql语句提交,从前到后依次执行。中间遇到错误所有修改一并回滚。

刚好就是背景里遇到的问题。

结合对odoo并行事务隔离级别的了解。加上自动提交事务的特性,手动提交事务确实能避免大事务的提交,同时效率可能有所降低,

但是和请求第三方api的时间相比,微不足道。

对于手动提交事务的风险,是修改不可逆,一旦提交发现问题回滚不了。

在程序中,错误的修改数据,如果不是抛出异常,也无法获取,最后还是一并提交,不能回滚。

关于是否能手动提交,我们还要在不同的使用场景中做实验才能确定是否会发生风险。

 

标签:事务,手动,回滚,odoo,提交,sql,数据
From: https://www.cnblogs.com/mu-tang/p/17122917.html

相关文章

  • odoo视图跳转流程
    引子:在学习和使用odoo过程中,习惯了点击创建就到新增页,点击编辑就能进入到详情页,点击返回就能回到列表页,那你有没有某一刻思考一下,这种页面跳转是以什么方式进行的呢,前后......
  • Windows 10 无网络的情况下手动升级补丁的流程和方法:
    Windows10无网络的情况下手动升级补丁的流程和方法:从微软官网下载需要的更新补丁;将下载的更新补丁保存到本地;打开“设置”,点击“更新和安全”;点击“查看可用更新”,......
  • 两阶段提交(实现逻辑上的一致)
    mysql在执行更新语句时,会同时记录redolog和binlog日志。为了保证这两个日志记录同样的数据,mysql通过两阶段提交,实现逻辑上的一致。在执行引擎更新到redolog后,redolog......
  • Flask Mysql 连接提交出错
    RuntimeError:Thesessionisunavailablebecausenosecretkeywasset. Setthesecret_keyontheapplicationtosomethinguniqueandsecret.出错如上所示原......
  • windows中使用git,vscode提交代码
    一.使用Gitbash操作1.准备条件与初始化新建一个文件夹dm-configcddm-config#初始化gitinit#全局配置添加邮箱和用户名gitconfig--globaluser.name"jack"......
  • redis中,如何手动重写aof文件?
    手动执行命令,生成aof文件:#1、进入redis客户端redis-cli#2、执行aof重写命令bgrewriteaof  执行效果:[root@nccztsjb-node-15redis-34992]#bin/redis-cli......
  • git 创建远程源 并提交代码
    一、提交代码到远程源1、gitremote2、gitremote-v3、gitremoteadd自己起的名字git的仓库地址(http)gitremoteaddsourcehttps://codeup.aliyun.com/cip-games.......
  • virtualBox Ubuntu挂载共享文件夹失败,手动mount -t vboxsf 失败 sbin/mount.vboxsf: m
    Windows使用virtualBox安装了Ubuntu虚拟机,更新过后,其他的共享文件夹,挂载出现了问题:就是挂载的目录和宿主源目录不同步了。  使用mount-tvboxsf命令手动挂载报错:sbi......
  • 7.项目结构的构建和提交到gitee
    创建微服务模块以商城项目的产品模块为例  点击Next,然后倒入依赖的包,SpringWeb 然后在选择一个微服务和微服务之间调用需要的包:OpenFeign 导入这两个微服务的......
  • 关于如何查看一个项目各个人的提交的代码行数
    在实际开发中,常常会想查看自己对于某个项目的贡献,管理者会查看项目下各成员的贡献,就需要使用到git的命令进行代码提交的统计。一、gitbash打开右键点击GitBashHere......