pymysql
pymysql 是在py3和py2上都可以使用的连接 MySQL 服务器的一个库。
事务
事务机制可以确保数据一致性。
事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
- 原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
- 一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
- 隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
- 持久性(durability)。持续性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
Python DB API 2.0 的事务提供了两个方法 commit 或 rollback。
安装
首先查看了conda库中是否有这个包conda search pymysql
,发现是有的并且有py2.7版本,直接安装conda install pymysql
cursor游标
游标就像一辆货车,把指令带过去执行(execute),然后运回来值(fetch*)。
fetch
- fetchone(): 该方法获取下一个查询结果集。结果集是一个对象
- fetchall(): 接收全部的返回结果行.
- rowcount: 这是一个只读属性,并返回执行execute()方法后影响的行数。
使用
## 建立数据库连接
conn = pymysql.Connect(host='127.0.0.1',
user='root',
passwd='123456',
db='python_mysql',
charset='utf8')
# 使用 cursor() 方法创建一个游标对象 cursor
# 每一个游标对象传送一条sql
cursor = conn.cursor()
# 使用 execute() 方法执行 SQL 查询
cursor.execute("SELECT VERSION()")
# 使用 fetchone() 方法获取单条数据.两个单词tetch one
# fetchall() 所有
conn.commit()
data = cursor.fetchone()
print ("Database version : %s " % data)
# 关闭数据库连接
db.close()
代码
转账:
# -*- coding: UTF-8 -*-
import sys
import pymysql
class TransferMoney(object):
def __init__(self, conn):
self.conn = conn
def check_acct_available(self, acctid):
cursor = self.conn.cursor()
try:
sql = "select * from account where acctid=%s" % acctid
cursor.execute(sql)
print "check_acct_available: " + sql
rs = cursor.fetchall()
if len(rs) !=1:
raise Exception("账号%s不存在" % acctid)
finally:
#关闭cursor
cursor.close()
def has_enough_money(self, acctid, money):
cursor = self.conn.cursor()
try:
sql = "select money from account where acctid=%s and money >= %s " % (acctid, money)
cursor.execute(sql)
print "has_enough_money: " + sql
rs = cursor.fetchall()
if len(rs) != 1:
raise Exception("账号%s金额不足,剩余金额为%s"%(acctid, money))
finally:
cursor.close()
def reduce_money(self, acctid, money):
cursor = self.conn.cursor()
try:
sql = "update account set money = money - %s where acctid=%s"%(money, acctid)
cursor.execute(sql)
print "reduce_money: " + sql
if cursor.rowcount !=1 :
raise Exception("账号%s减款失败"%(acctid))
finally:
cursor.close()
def add_money(self, acctid, money):
cursor = self.conn.cursor()
try:
sql = "update account set money = money + %s where acctid=%s"%(money, acctid)
cursor.execute(sql)
print "add_money: " + sql
if cursor.rowcount !=1 : #判断被影响的行数:cursor.rowcount
raise Exception("账号%s加款失败"%(acctid))
finally:
cursor.close()
def transfer(self, source_acctid, target_acctid, money):
try:
self.check_acct_available(source_acctid)
self.check_acct_available(target_acctid)
self.has_enough_money(source_acctid, money)
self.reduce_money(source_acctid, money)
self.add_money(target_acctid, money)
# 向数据库提交,不开启自动提交
self.conn.commit()
except Exception as e:
# 发生错误时回滚
self.conn.rollback()
raise e
if __name__ == "__main__":
source_acctid = sys.argv[1]
target_acctid = sys.argv[2]
money = sys.argv[3]
conn = pymysql.Connect(host='127.0.0.1',
user='root',
passwd='123456',
db='python_mysql',
charset='utf8'
)
tr_money = TransferMoney(conn)
try:
tr_money.transfer(source_acctid, target_acctid, money)
except Exception as e:
print "出现问题:" + str(e)
finally:
# 关闭连接
conn.close()
引用
1. http://www.runoob.com/python3/python3-mysql.html
2. PyMySQL’s documentation
3. https://github.com/PyMySQL/PyMySQL
4. https://www.python.org/dev/peps/pep-0249/