sqlalchemy lock and atomic
prepare:
Prepare a table
set evn
- DBUSER=root
- DBPASS=
- DBNAME=cyborg
TBNAME="atomic"
RDNAME="s0"
DB create
- DBNAME=atomic
- mysql -u$DBUSER -p$DBPASS <<< "create DATABASE $DBNAME"
Delete DB
- mysql -u$DBUSER -p$DBPASS <<< "drop database $DBNAME"
table create
- mysql -u$DBUSER -p$DBPASS $DBNAME <<< "CREATE TABLE $TBNAME(
- id INT NOT NULL AUTO_INCREMENT,
- name VARCHAR(100) NOT NULL,
- PRIMARY KEY (id))ENGINE=InnoDB DEFAULT CHARSET=utf8;
desc $TBNAME"
Delete table
- mysql -u$DBUSER -p$DBPASS $DBNAME <<< "DROP TABLE $TBNAME"
insert table
- mysql -u$DBUSER -p$DBPASS $DBNAME <<< "INSERT INTO $TBNAME
- (name)
- VALUES
- (\"s0\");"
update table
- TBNAME="atomic"
- RDNAME="s0"
- mysql -u$DBUSER -p$DBPASS $DBNAME <<<"UPDATE $TBNAME SET name='$RDNAME' WHERE id=1"
数据库锁(DB lock)
sqlalchemy 使用with_lockmode锁住DB锁(不是
sqlalchemy 实现的锁)
test.py 如下:
- from sqlalchemy import create_engine,Table,Column,Integer,String,MetaData,ForeignKey
- from sqlalchemy.orm import sessionmaker, scoped_session
- from sqlalchemy.orm import relationship, backref
- from sqlalchemy.ext.declarative import declarative_base
- import time
- import sys
- print(sys.argv)
- mode = sys.argv[1] if len(sys.argv) > 1 else "get"
- print("DB for %s" % mode)
- Base = declarative_base()
- Session = sessionmaker()
- engine = create_engine("mysql://root:123@localhost/cyborg")
- Session.configure(bind=engine)
- session = Session()
- class Atomic(Base):
- __tablename__ = 'atomic'
- id = Column(Integer, primary_key=True)
- name = Column(String)
- def __str__(self):
- return 'Atomic[%d, %s]' % (self.id, self.name)
- at_id = 1
- filer_name = "s0"
- exp_name = "s1"
- wait = 10
- print("start to get lock", time.strftime("%H:%M:%S"))
- if mode == "get":
- lock = session.query(Atomic).with_for_update().filter(
- Atomic.id == at_id).first()
# remove with_for_update, "update" mode no need wait to get lock- print("get lock: ", time.strftime("%H:%M:%S"))
- print(lock)
- print("lock the record and wait for %s", wait)
- time.sleep(wait)
- session.commit()
- else:
- lock = session.query(Atomic).filter_by(name=filer_name).with_for_update().update(
- {"name": exp_name}, synchronize_session="fetch")
- print(lock)
- print("get lock: ", time.strftime("%H:%M:%S"))
- print("update the record and wait for %s", wait)
- time.sleep(wait)
- session.commit()
- print(lock)
先执行update,再read
在terminal 1执行:
- python2 test.py update
在terminal 2执行:
- python2 test.py
很明显读取需要等待时间。
或者
- mysql -u$DBUSER -p$DBPASS $DBNAME <<< "select * from $TBNAME"
不需要等待时间。
先执行read ’python2 test.py’,再update也需要等待。
New in version 0.9.0: Query.with_for_update() supersedes the Query.with_lockmode() method.
结论:
update的时候,即使不指定with_for_update, 也会自动获取这个update锁。
仅仅query的时候,如果不指定with_for_update, 那么立即执行,不会获取这个锁。
sqlalchemy session 执行 delete 时 synchronize_session 策略 (update 同样适用)
False: 不同步 session,如果被删除的 objects 已经在 session 中存在,在 session commit 或者 expire_all 之前,这些被删除的对象都存在 session 中。
不同步可能会导致获取被删除 objects 时出错。
fetch: 删除之前从 db 中匹配被删除的对象并保存在 session 中,然后再从 session 中删除,这样做是为了让 session 的对象管理 identity_map 得知被删除的对象究竟是哪些以便更新引用关系。
evaluate: 默认值。根据当前的 query criteria 扫描 session 中的 objects,如果不能正确执行则抛出错误,这句话也可以理解为,如果 session 中原本就没有这些被删除的 objects,扫描当然不会发生匹配,相当于匹配未正确执行。
- from sqlalchemy import create_engine,Table,Column,Integer,String,MetaData,ForeignKey
- from sqlalchemy.orm import sessionmaker, scoped_session
- from sqlalchemy.orm import relationship, backref
- from sqlalchemy.ext.declarative import declarative_base
- Base = declarative_base()
- Session = sessionmaker()
- engine = create_engine("mysql://root:123@localhost/cyborg")
- Session.configure(bind=engine)
- session = Session()
- class Atomic(Base):
- __tablename__ = 'atomic'
- id = Column(Integer, primary_key=True)
- name = Column(String)
- q = session.query(Atomic)
- a = q.filter_by(name="s1")
- print(type(a))
- print(a)
- at = a.one()
- print(a.one())
- import ipdb; ipdb.set_trace()
- # "fetch" "evaluate"
- a1 =a.update({"name": "s2"}, synchronize_session=False)
- print(type(a1))
- print(a1)
- print(Atomic.name=="s1")
- session.commit()
- print(a.one())
REF:
SQL Atomic Operation on UPDATE and DELETE
SQLAlchemy ORM Examples (推荐,一个系列,一共11个部分)
Cyborg DB example:
mysql:
- DBUSER=root
- DBPASS=y0devstk
- DBNAME=cyborg
- TBNAME="attach_handles"
- RDNAME=0
- FIELD="in_use"
- QR_NAME="deployable_id"
- QR_VALUE=`mysql -u$DBUSER -p$DBPASS $DBNAME <<<"SELECT $QR_NAME FROM $TBNAME LIMIT 1" | tail -n 1`
- mysql -u$DBUSER -p$DBPASS $DBNAME <<<"UPDATE $TBNAME SET $FIELD=$RDNAME WHERE $QR_NAME=$QR_VALUE"
- mysql -u$DBUSER -p$DBPASS $DBNAME <<<"SELECT $FIELD FROM $TBNAME WHERE $QR_NAME=$QR_VALUE"
python
- import cyborg.conf
- import cyborg.db.sqlalchemy.models
- from oslo_db import options
- from cyborg import context
- from cyborg import db as db_api
- user="root"
- psw="y0devstk"
- # connection_debug=1,
- # connection_trace=True,
- # set_override
- CONF = cyborg.conf.CONF
- CONF(["--config-file=/etc/cyborg/cyborg.conf"])
- options.set_defaults(CONF)
- # options.set_defaults(CONF,
- # connection="mysql+pymysql://%s:%s@127.0.0.1/cyborg?charset=utf8" % (user, psw))
- print(CONF["database"].items())
- # from oslo_context import context
- ct = context.get_admin_context()
- sqlalchemy_api = db_api.get_instance()
- try:
- r = sqlalchemy_api.attach_handle_list(ct)
- r0 = r[0]
- print(r0.in_use)
- # r = sqlalchemy_api.attach_handle_allocate(ct, r0.attach_type, r0.deployable_id)
- r1 = sqlalchemy_api.attach_handle_allocate(ct, r0.deployable_id)
- print(r1.in_use)
- except Exception as e:
- print(e)
openstack oslo.config
sqlalchemy lock and atomic的更多相关文章
- ReetrantLock Synchronized Atomic的性能对比
之前看到了一篇帖子关于Lock和Synchronized的性能,写的是Lock比Synchronized的性能要好,可是,我试了下,结果却不是这样的,我所使用的JDK的版本是1.7,可能跟原帖作者用的 ...
- java中的Atomic类
文章目录 问题背景 Lock 使用Atomic java中的Atomic类 问题背景 在多线程环境中,我们最常遇到的问题就是变量的值进行同步.因为变量需要在多线程中进行共享,所以我们必须需要采用一定的 ...
- 工作队列(workqueue) create_workqueue/schedule_work/queue_work
--- 项目需要,在驱动模块里用内核计时器timer_list实现了一个状态机.郁闷的是,运行时总报错"Scheduling while atomic",网上搜了一下:" ...
- go sync.Mutex 设计思想与演化过程 (一)
go语言在云计算时代将会如日中天,还抱着.NET不放的人将会被淘汰.学习go语言和.NET完全不一样,它有非常简单的runtime 和 类库.最好的办法就是将整个源代码读一遍,这是我见过最简洁的系统类 ...
- [内核]Linux workqueue
转自:http://blog.chinaunix.net/uid-24148050-id-296982.html 一.workqueue简介workqueue与tasklet类似,都是允许内核代码请求 ...
- JAVA并发的性能调整
1.互斥技术 synchronized Lock Atomic 性能比较Atomic > Lock > synchronized,当然这不是绝对的.当线程数比较少时,synchroni ...
- Java并发控制机制详解
在一般性开发中,笔者经常看到很多同学在对待java并发开发模型中只会使用一些基础的方法.比如Volatile,synchronized.像Lock和atomic这类高级并发包很多人并不经常使用.我想大 ...
- obj-c编程10:Foundation库中类的使用(6)[线程和操作队列]
任何语言都不能避而不谈线程这个东东,虽然他是和平台相关的鸟,虽说unix哲学比较讨厌线程的说...线程不是万能灵药,但有些场合还是需要的.谈到线程就不得不考虑同步和死锁问题,见如下代码: #impor ...
- Java编程思想 - 并发
前言 Q: 为什么学习并发? A: 到目前为止,你学到的都是有关顺序编程的知识,即程序中的所有事物在任意时刻都只能执行一个步骤. A: 编程问题中相当大的一部分都可以通过使用顺序编程来解决,然而,对于 ...
随机推荐
- 怎样遍历NodeList对象
因为NodeList对象是一个类似数组的对象, 且它自带了一个 forEach() 方法, 因此可以使用 forEach() 遍历, 它的用法和 Array 里面的 forEach() 是完全一样的. ...
- (转)微服务_创建一个简单的Eureka注册中心
原文地址:https://www.cnblogs.com/lplshermie/p/9105329.html 微服务和分布式已经成了一种极其普遍的技术,为了跟上时代的步伐,最近开始着手学习Spring ...
- MVC通过ViewBag动态生成Html输出到View
今天再给自己总结一下,关于ViewBag赋值Html格式值,但是在web页显示不正常; 例如,ViewBag.Content = "<p>你好,我现在测试一个东西.</p& ...
- RStudio中安装factoextra包的问题
最近在做一个R语言的小作业,其中聚类分析部分需要用到factoextra安装包,在RStudio中输入install.packages("factoextra")之后,就一直出现“ ...
- php精度比较函数bccomp
bccomp (PHP 4, PHP 5, PHP 7) bccomp — 比较两个任意精度的数字 说明 int bccomp ( string $left_operand , string $rig ...
- Flink原理、实战与性能优化读书笔记
第一章 ApacheFlink介绍 一.Flink优势 1. 目前唯一同时支持高吞吐.低延迟.高性能的分布式流式数据处理框架 2. 支持事件事件概念 3. 支持有状态计算,保持了事件原本产生的时序性, ...
- 【Jmeter】他人总结篇链接(共八篇相关文章)
[Jmeter]他人总结篇链接(共八篇相关文章) https://blog.csdn.net/mu_wind/article/category/9029006
- k8s维护常用命令
k8s维护 1. 不可调度 kubectl cordon k8s-node-1 kubectl uncordon k8s-node-1 #取消 2.驱逐已经运行的业务容器 kubectl drain ...
- 什么是SAP Intelligent Robitic Process Automation - iRPA
所谓智慧企业,一个特征就是具备将复杂但低附加值的重复流程通过自动化的方式完成的能力.通过自动化,从而将宝贵的人力资源投入到更高附加值的工作中去,比如提供产品和服务的品质,提升用户体验.SAPGUI时代 ...
- fiddler证书问题
1.清除C:\Users\Administrator\AppData\Roaming\Microsoft\Crypto\RSA 目录下所有文件(首次安装fiddler请忽略) 2.清除电脑上的根证书, ...