通过pymysql程序debug学习数据库事务、隔离级别
问题
今天在使用pymysql连数据库的时候,出现了一个bug,查询数据库某个数据,但是在我在数据库中执行sql语句改变数据后,pymsql的查询依然没有发生改变。
代码如下:
# 5.6.10
conn = pymysql.connect(host=HOST, port=PORT, user=USER, passwd=PSWD, db=DB)
def fetch():
cursor = conn.cursor()
sql = "SELECT * FROM hello"
try:
res = cursor.execute(sql)
except:
pass
finally:
cursor.close()
for data in cursor.fetchall():
print(*data)
while True:
fetch()
time.sleep(2)
解决问题
首先,我们还是找出问题原因,并解决它,查阅相关文档后可知,因为我们的查询语句执行后,没有commit()
,这会导致查询事务没有提交,mysql数据库会返回上次查询到的结果。
所以,不管是增删查改,最好都以事务的形式提交!
try:
res = cursor.execute(sql)
conn.commit()
except:
pass
finally:
cursor.close()
分析
接下来我们来仔细分析,为什么查询也需要提交事务
- 数据库的事务
- 脏读、不可重复读、幻读
- 数据库事务隔离级别
- 数据库的锁
1.数据库的事务特性
先简单了解数据库事务的特性
- 原子性:原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生要么都不发生。
- 一致性:如果事务执行之前数据库是一个完整性的状态,那么事务结束后,无论事务是否执行成功,数据库仍然是一个完整性状态.
数据库的完整性状态:当一个数据库中的所有的数据都符合数据库中所定义的所有的约束,此时可以称数据库是一个完整性状态. - 隔离性:事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间事务要隔离
- 持久性:持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响
2.脏读、不可重复读、幻读
脏读(读取未提交的数据)
转账 | 取钱 |
---|---|
事务开始 | |
事务开始 | |
查看余额为2000 | |
取钱1000 | |
查余额为1000 | |
未知错误,事务回滚,余额为2000 | |
转账2000,余额为3000(脏读1000+2000) | |
事务提交 |
所以莫名其妙就少了1000块钱
不可重复读(两次读取结果不一致)
拿购物和取钱说事,有天小A去取钱,看余额有2000块(事务开始),很开心,此时她老婆看到喜欢的东西,手速极快的下单,付款2000(其他事务提交完成),这时小A到ATM取1000块钱,ATM提示余额不足!小A感到很疑惑,刚才明明还有2000的啊?
取钱 | 购物 |
---|---|
事务开始 | |
查看余额为2000 | |
事务开始 | |
消费2000 | |
事务提交 | |
再次查询余额为0 | |
事务结束 |
幻读(多次读取,总量不一样)
这天,小A查自己这个月的账单(事务开始),发现5笔购物总计消费1000块,这时,他老婆又眼疾手快的下单付款买了一件衣服2000块(其他事务结束),这时,小A再看他的账单,总计消费变成了3000块,就像产生幻觉一样(事务结束)
查账 | 购物 |
---|---|
事务开始 | |
查看账单为1000 | |
事务开始 | |
增加一笔账单2000 | |
事务提交 | |
再次查看账单为3000 | |
事务结束 |
不可重复读和幻读的区别
可能到这,大概了解了3种读取数据会出现的异常情况了,但可能对不可重复读和幻读有疑问,似乎差不多啊。
可以这么理解,不可重复读是针对于数据库表的某条记录而言,也就是针对update一些。解决办法例如:我们可以在读取事务进行的时候对该条记录加锁,以避免重复读不一致的问题。
幻读是针对多条记录而言,针对insert,delete一些,在同一事务两次查询结果数目不一致。解决办法例如:我们可以在读取事务进行的时候对整个表加锁,以避免。
3.数据库的隔离级别
数据库的隔离级别,由低到高依次为Read uncommitted 、Read committed 、Repeatable read 、Serializable ,这四个级别可以逐个解决脏读 、不可重复读 、幻读 这几类问题。
√可以避免,×不能避免
脏读 | 不可重复读 | 幻读 | |
---|---|---|---|
Read uncommitted | × | × | × |
Read committed | √ | × | × |
Repeatable read | √ | √ | × |
Serializable | √ | √ | √ |
而mysql默认为 Repeatable read,Sql Server , Oracle默认为 Read committed
到这里,基本可以完结今天的bug原因了,mysql可以避免重复读的问题的,它并不是通过前面提到的加锁来控制的,而是,同一事务的查询结果都是事务开始的时候保存的快照,所以如果不commit,查询结果不会改变!
4.数据库的锁
还想继续深究数据库是如何加锁来保证事务的四大特性的。有时间一定去了解,到时候来更新。。。哈哈
InnoDB锁机制
通过pymysql程序debug学习数据库事务、隔离级别的更多相关文章
- 数据库事务隔离级ORACLE数据库事务隔离级别介绍
本文系转载,原文地址:http://singo107.iteye.com/blog/1175084 数据库事务的隔离级别有4个,由低到高依次为Read uncommitted.Read committ ...
- Atitit.数据库事务隔离级别 attilax 总结
Atitit.数据库事务隔离级别 1. 事务隔离级别的作用 1 2. 在的隔离级别 2 3. 常见数据库的默认管理级别 3 1. 事务隔离级别的作用 较低的隔离级别可以增强许多用户同时访问数据的能力, ...
- Mysql数据库事务隔离级别
事务(transaction)是数据库管理系统的执行单位,可以是一个数据库操作(如Select操作)或者是一组操作序列.事务ACID属性,即原子性(Atomicity).一致性(Consistency ...
- 数据库事务隔离级别+Spring 声明性事务隔离级别
数据库事务隔离级别 数据库提供了四种事务隔离级别, 不同的隔离级别采用不同的锁类开来实现. 在四种隔离级别中, Serializable的级别最高, Read Uncommited级别最低. 大多数数 ...
- MySQL数据库事务隔离级别(Transaction Isolation Level)
转自: http://www.cnblogs.com/zemliu/archive/2012/06/17/2552301.html 数据库隔离级别有四种,应用<高性能mysql>一书中的 ...
- 数据库事务隔离级别<转>
数据库事务的隔离级别有4个,由低到高依次为Read uncommitted.Read committed.Repeatable read.Serializable,这四个级别可以逐个解决脏读.不可重复 ...
- MSSQL数据库 事务隔离级别
数据库事务的隔离级别有4个,由低到高依次为Read uncommitted .Read committed .Repeatable read .Serializable ,这四个级别可以逐个解 脏读 ...
- ORACLE数据库事务隔离级别
转自:https://www.cnblogs.com/jackal/archive/2011/02/14/1954231.html 事务隔离级别:一个事务对数据库的修改与并行的另一个事务的隔离程度. ...
- mysql事务之一:MySQL数据库事务隔离级别(Transaction Isolation Level)及锁的实现原理
一.数据库隔离级别 数据库隔离级别有四种,应用<高性能mysql>一书中的说明: 然后说说修改事务隔离级别的方法: 1.全局修改,修改mysql.ini配置文件,在最后加上 1 #可选参数 ...
随机推荐
- 大型网站技术架构(3):WEB 前端性能优化
上次说到了性能优化策略,根据网站的分层架构,可以大致的分为 web 前端性能优化,应用服务器性能优化,存储服务器性能优化三大类 这次来说一下 web 前端性能优化,一般来说,web 前端就是应用服务器 ...
- HTML中css和js链接中的版本号
背景 在搜索引擎中搜索关键字.htaccess 缓存,你可以搜索到很多关于设置网站文件缓存的教程,通过设置可以将css.js等不太经常更新的文件缓存在浏览器端,这样访客每次访问你的网站的时候, 浏览器 ...
- 权限管理系统(四):RBAC权限模型分类介绍
RBAC是Role-BasedAccess Control的英文缩写,意思是基于角色的访问控制.RBAC认为权限授权实际上是Who.What.How的问题.在RBAC模型中,who.what.how构 ...
- C++ 模板详解 肥而不腻
C++模板 模板是C++支持参数化多态的工具,使用模板可以使用户为类或者函数声明一种一般模式,使得类中的某些数据成员或者成员函数的参数.返回值取得任意类型. 模板是一种对类型进行参数化的工具: 通常有 ...
- Atitit.软件控件and仪表盘(23)--多媒体子系统--视频输出切换控制cvbs av s-video Ypbpr pal ntsc
Atitit.软件控件and仪表盘(23)--多媒体子系统--视频输出切换控制cvbs av s-video Ypbpr pal ntsc 1. CVBS是AV接口 1 2. S-Video S端子 ...
- 起航,第一个程序——还是LED灯
如同学基本语言一样,helloworld是很多语言的第一个程序.在嵌入式开发中,点亮LED灯也是各种架构和开发板的第一个程序,其中很多东西是和单片机例如stm32是类似的,只是,现在我们没有了库函数, ...
- 改进cocos2dx中lua读ccb的方法
cocos2dx自带的CCBProxy真弱,还好提供了一个CCBReaderLoader.lua,但是也不好用, 于是修改了一下CCBReaderLoader,下面直接贴代码了. function N ...
- cocos2dx遇到的一些坑
针对2.x 1.CCSprite无法直接用文件名更换图片,可以添加如下函数 bool CCSprite::setWithFile(const char *pszFilename) { CCAssert ...
- ipipe-3.10
git://git.xenomai.org/ipipe-gch.git for-ipipe-3.10
- zabbix监控数据库
Zabbix通过percona监控MySQL 因为Zabbix自带的MySQL监控没有提供可以直接使用的Key,所以一般不采用,业界的同学们都使用Percona Monitoring Plugin ...