Python-数据库支持

10、Python-数据库支持

使用数据库的好处:

a、支持数据的并发访问,多个用户同时对基于磁盘的数据进行读写而不造成任何文件的损坏;

b、支持根据多个数据字段或属性进行复杂的搜索;

1、如何操作数据库,API

数据库的种类有很多,并且它们的功能基本都是一样的,为了对数据库进行统一的操作,大多数语言都提供了简单的、标准化的数据库接口(API)。为了易于编写跨数据库的程序,所有数据库的包装模块都应当遵循这个接口。

2、支持的API函数

连接数据库connect(),该函数返回连接对象,代表了与要连接的数据库的会话。连接对象支持一下方法:

close()  关闭连接之后,连接对象和它的游标均不可用
commit() 如果支持的话提交挂起的事务,否则不做任何事
rollback() 回滚挂起的事务
cursor() 返回连接的游标对象(通过游标对象执行SQL查询并检查结果,结果行可以一个一个地获得,也可以很多个一起获得)

游标对象的方法:

callproc(name[,params]) 使用给定的名称和参数(可选)调用已命名的数据库程序
close() 关闭游标之后,游标不可用
execute(oper[,params]) 执行SQL参数,可能使用参数
executemany(opr, pseq) 对序列中的每个参数执行SQL操作
fetchone() 把查询的结果集中的下一行保存为序列,或者None
fetchmany([size]) 获取查询结果集中的多行,默认尺寸为arraysize
fetchall() 以序列的形式获取结果集中的所有行
nextset() 跳至下一个可用的结果集(可选)
setinputsizes(sizes) 为参数预先定义内存区域
setoutputsize(size[,col]) 为获取的大数据值设定缓冲区尺寸

游标对象特性:

description 结果列描述的系列,只读
rowcount 结果中的行数,只读
arraysize fetchmany中返回的行数,默认为1

         

3、程序示例

以SQLite数据库为例,它是小型的嵌入式SQL数据库,它的python包装叫做PYSQLite。它速度快,易于使用,并且不需要建立单独的服务器。

3.1 创建和填充表

复制代码
 1 import sqlite
 2 
 3 def convert(value):
 4     if value.startswith('~'):
 5         return value.strip('~')
 6     if not value:
 7         value = '0'
 8     return float(value)
 9 
10 conn = sqlite.connect('food.db')
11 curs = conn.cursor()
12 
13 curs.execute('''
14 CREATE TABLE food (
15   id         TEXT       PRIMARY KEY,
16   desc       TEXT,
17   water      FLOAT,
18   kcal       FLOAT,
19   protein    FLOAT,
20   fat        FLOAT,
21   ash        FLOAT,
22   carbs      FLOAT,
23   fiber      FLOAT,
24   sugar      FLOAT
25 )
26 ''')
27 
28 field_count = 10
29 markers = ', '.join(['%s']*field_count)
30 query = 'INSERT INTO food VALUES (%s)' % markers
31 
32 for line in open('ABBREV.txt'):
33     fields = line.split('^')
34     vals = [convert(f) for f in fields[:field_count]]
35 curs.execute(query, vals)
36 
37 conn.commit()
38 conn.close()
复制代码

3.2 搜索和处理结果

复制代码
 1 import sqlite, sys
 2 
 3 conn = sqlite.connect('food.db')
 4 curs = conn.cursor()
 5 
 6 query = 'SELECT * FROM food WHERE %s' % sys.argv[1]
 7 print query
 8 curs.execute(query)
 9 names = [f[0] for f in curs.description]
10 for row incurs.fetchall():
11     for pair in zip(names, row):
12         print '%s: %s' % pair
13     print
复制代码


 

 
 
分类: Python技术相关

DDD:如何处理“唯一性”业务逻辑

背景

唯一性约束是一个经常出现的业务逻辑,刚开始我觉得非常简单,不过深入考虑后,发现实现起来还不是那么简单,下面就让我们分析一下。

两种场景下的唯一性约束

第一种场景:聚合根的某个属性的唯一性约束

示例:用户的用户名必须唯一。

第一种实现思路:后验证+不用数据库索引,在插入用户名和修改用户名之后执行一次验证,这个验证逻辑执行的事务隔离级别必须处于“读未提交”级别。

复制代码
 1 public volid Insert(User user)
 2 {
 3     using(var ts1 = new TransactionScope("读已提交"))
 4     {
 5         DoInsert(user);
 6         using(var ts2 = new TransactionScope("读未提交"))
 7         {
 8             //如果违背约束,抛出异常。
 9         }
10         ts1.Complete();
11     }
12 }
复制代码

 第二种实现思路:前验证+不用数据库索引,在插入用户名和修改用户名之前执行一次验证,整个事务运行在“串行化”隔离级别。

复制代码
1 public volid Insert(User user)
2 {
3     using(var ts = new TransactionScope("串行化"))
4     {            
5         //如果违背约束,抛出异常。
6         DoInsert(user);
7         ts.Complete();
8     }
9 }
复制代码

 第三种实现思路:前验证+数据库索引,在插入用户名和修改用户名之前执行一次验证,整个事务运行在“读已提交”隔离级别。

复制代码
1 public volid Insert(User user)
2  {
3      using(var ts = new TransactionScope("读已提交"))
4      {            
5          //如果违背约束,抛出异常。
6          DoInsert(user);
7          ts.Complete();
8      }
9  }
复制代码

 第四实现思路种:内存锁。

有朋友会想,为啥不直接用数据库索引呢?失败了就跑出异常,因为我们需要收集到友好的异常信息显示给UI,所以才需要在程序里判定唯一性,然后抛出友好的异常信息。

总体来说我觉得第三种思路在现实中比较方便。

第二种场景:聚合内某个实体的属性的唯一性约束

示例:订单的订单项的产品必须唯一。

第一种实现思路:聚合根的乐观锁+聚合自身必须保证这种约束。

我觉得这个场景下只有这一种实现是比较合理的,就不介绍其他思路了。

备注

在健身房仓促写就,大家多提意见。

 
分类: DDD

Jexus vs IIS8 非绝对客观对比测试

 

特别说明,如标题说的,如下测试并非绝对客观,仅仅是本人实际生产环境应用中的测试,给大家做个参考 O(∩_∩)O~

测试服务器

1) Win 2012 DC 4核 2GB,.Net 4.0,IIS8

2) Ubuntu 12.04.2 LTS 64位 4核 2GB,Mono 3.0.11,Jexus 5.3.1 开2 线程

3) 单台HAProxy 1.4.23(Ubuntu 12.04.2 LTS 64位 4核 512MB)做负载均衡,

两台Ubuntu 12.04.2 LTS 64位 4核 1GB,Mono 3.0.11,Jexus 5.3.1 开2 线程【这也是我们准备使用的实际生产环境 O(∩_∩)O~】

【注:以上测试服务器全是在一台服务器上使用Hyper-v 2012虚拟出来的VPS】

测试工具:webbench 1.5

测试内容

1)静态页面

一个好简单的页面 (^o^)/~ 

2)动态页面

里面只有一个输出图片流的Webapi (基于MVC4),数据流完全来自后面两台redis,所以是纯内存运算,撇开了磁盘io性能对测试的影响;同时所有测试代码都直接在Win下使用.Net库编译,没有特别针对Mono进行重新编译,因为实际生产环境就是用VS开发,Linux下部署,做到部署开发双赢 O(∩_∩)O~

测试结果

Win 2012 DC 4核 2GB,.Net 4.0,IIS8 

静态网页

webbench -c 2000 -t 60 http://xxx.../Test.html

第一轮:

Speed=988904 pages/min, 6954750 bytes/sec.

Requests: 988830 susceed, 74 failed.

第二轮:

Speed=919040 pages/min, 6463085 bytes/sec.

Requests: 918922 susceed, 118 failed.

第三轮:

Speed=950179 pages/min, 6682743 bytes/sec.

Requests: 950154 susceed, 25 failed.

动态页面

webbench -c 2000 -t 60 http://xxx.../api/imageapi/jpg/404

第一轮: 

Speed=86178 pages/min, -16884928 bytes/sec.

Requests: 86178 susceed, 0 failed.

第二轮:

Speed=70078 pages/min, -25869144 bytes/sec.

Requests: 70078 susceed, 0 failed.

第三轮:

Speed=86589 pages/min, -15101846 bytes/sec.

Requests: 86589 susceed, 0 failed.

Ubuntu 12.04.2 LTS 64位 4核 2GB,Mono 3.0.11,Jexus 5.3.1 开2 线程

静态网页

webbench -c 2000 -t 60 http://xxx.../Test.html

第一轮:

Speed=1071175 pages/min, 7210827 bytes/sec.

Requests: 1070916 susceed, 259 failed.

第二轮:

Speed=916569 pages/min, 6171551 bytes/sec.

Requests: 916568 susceed, 1 failed.

第三轮:

Speed=1278075 pages/min, 8605698 bytes/sec.

Requests: 1278075 susceed, 0 failed.

动态页面

webbench -c 2000 -t 60 http://xxx.../api/imageapi/jpg/404

第一轮:

Speed=30748 pages/min, 19972172 bytes/sec.

Requests: 30748 susceed, 0 failed.

第二轮:

Speed=55311 pages/min, 33876640 bytes/sec.

Requests: 55184 susceed, 127 failed.

第三轮:

Speed=50942 pages/min, 33090642 bytes/sec.

Requests: 50942 susceed, 0 failed.

【注:测试期间,jexus有一次出现cpu 100%的无响应状态,restart后,就暂时重现不出来,所以暂不知道是什么原因 ╮(╯_╰)╭】

单台HAProxy 1.4.23(Ubuntu 12.04.2 LTS 64位 4核 512MB)做负载均衡

两台Ubuntu 12.04.2 LTS 64位 4核 1GB,Mono 3.0.11,Jexus 5.3.1 开2 线程

静态网页

webbench -c 2000 -t 60 http://xxx.../Test.html

第一轮:

Speed=409062 pages/min, 2754351 bytes/sec.

Requests: 409062 susceed, 0 failed.

第二轮:

Speed=411590 pages/min, 2769466 bytes/sec.

Requests: 411590 susceed, 0 failed.

第三轮:

Speed=408758 pages/min, 2752304 bytes/sec.

Requests: 408758 susceed, 0 failed.

动态页面

webbench -c 2000 -t 60 http://xxx.../api/imageapi/jpg/404

第一轮:

Speed=85647 pages/min, -16004347 bytes/sec.

Requests: 85647 susceed, 0 failed.

第二轮:

Speed=83603 pages/min, -17327404 bytes/sec.

Requests: 83603 susceed, 0 failed.

第三轮:

Speed=77596 pages/min, -21411556 bytes/sec.

Requests: 77596 susceed, 0 failed.

总结:静态输出方面,Jexus的性能不比IIS8差,甚至更好,动态解析方面是差一点(当中本身就有mono性能不及.net的关系,不过也差距不是很大;也有我冇优化使用Jexus的原因,Jexus最大线程可以开4个,我只使用了2个,也冇具体优化Linux配置;还有我负载均衡优化的不足,小弟我配置负载均衡还是初哥),但应用在生产环境完全够用,稳定性也很不错(虽然测试期间有宕机的情况,仅此一次,也重现不了,但毕竟是出现过一次,日后随版本更新,更多用户使用反馈优化,必然会更加稳定),加上使用相同的配置,组成群集的话,性能上已经比同配置单台IIS8差不多,高低难分,而且更稳定,实际生产应用还是很值得信赖 (^o^)/~。

结语:非常感谢 宇内流云 带给我们这样一个高性能的服务器!!!为廉价的部署方案开辟了一条光明大道!!!非常感谢!!!

Jexus官网:http://www.linuxdot.net/

原文地址:https://www.cnblogs.com/Leo_wl/p/3139238.html