解决pymysql不能实时查询最新的数据
#在网上查询到的原因为:
InnoDB 的默认隔离级别。它可以防止任何被查询的行被其他事务更改,从而阻止不可重复的读取,而不是 幻读取。它使用中度严格的锁定策略,以便事务内的所有查询都会查看同一快照中的数据,即数据在事务开始时的数据。
那么此时问题就找到了,跟当前的事务级别有关系的;当创建查询事务时,事务一直没有进行更新,每次查询到的数据都是之前查询结果的快照。
想要解决上述的问题,首先要明白mysql中事务这个概念,本地的mysql数据库是默认安装的,默认存储引擎是(InnoDB),事务隔离级别是(REPEATABLE READ):
查看存储引擎:
mysql> show engines; # 查看数据库支持的存储引擎
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine | Support | Comment | Transactions | XA | Savepoints |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| FEDERATED | NO | Federated MySQL storage engine | NULL | NULL | NULL |
| MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO |
| MyISAM | YES | MyISAM storage engine | NO | NO | NO |
| BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO |
| CSV | YES | CSV storage engine | NO | NO | NO |
| MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO |
| ARCHIVE | YES | Archive storage engine | NO | NO | NO |
| InnoDB | DEFAULT | Supports transactions, row-level locking, and foreign keys | YES | YES | YES |
| PERFORMANCE_SCHEMA | YES | Performance Schema | NO | NO | NO |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
9 rows in set (0.00 sec) mysql> show variables like '%storage_engine%'; # 当前的存储引擎
+----------------------------+--------+
| Variable_name | Value |
+----------------------------+--------+
| default_storage_engine | InnoDB |
| default_tmp_storage_engine | InnoDB |
| storage_engine | InnoDB |
+----------------------------+--------+
3 rows in set (0.00 sec)
查看当前的事务隔离级别:
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)
重复读(REPEATABLE READ):
InnoDB 的默认隔离级别。它可以防止任何被查询的行被其他事务更改,从而阻止不可重复的读取,而不是 幻读取。它使用中度严格的锁定策略,以便事务内的所有查询都会查看同一快照中的数据,即数据在事务开始时的数据。
REPEATABLE READ
The default isolation level for InnoDB. It prevents any rows that are queried from being changed by other transactions, thus blocking non-repeatable reads but not phantom reads. It uses a moderately strict locking strategy so that all queries within a transaction see data from the same snapshot, that is, the data as it was at the time the transaction started.
重复读
那么此时问题就找到了,跟当前的事务级别有关系的;当创建查询事务时,事务一直没有进行更新,每次查询到的数据都是之前查询结果的快照,下面会详细介绍每种事务隔离级别的区别
解决:
知道了具体原因是事务级别的问题,导致查询事务并没有更新,那么针对事务隔离级别进行应对就可以了,此类问题有三种解决方案,修改事务隔离级别、每次查询后更新事务、关闭数据库的事务(慎选)
① 每次查询后更新事务:
# 第一种方案,每次查询后进行commit操作,进行事务更新 import pymysql
import time
# Connect to the database
connection = pymysql.connect(host='192.168.1.134',
port=3306,
user='remote',
password='tx_1234abc',
db='Jefrey',
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor,
)
while True:
with connection.cursor() as cursor:
# Create a new record
sql = " select * from users WHERE email=%s"
# sql = "INSERT INTO `users` (`email`, `password`) VALUES (%s, %s)"
rows_count = cursor.execute(sql, ('webmaster@python.org'))
result = cursor.fetchall()
print(result)
connection.commit() # 新增
time.sleep(1) # 第二种方案,创建connect连接时,autocommit=True,自动进行commit提交
import pymysql
import time
# Connect to the database
connection = pymysql.connect(host='192.168.1.134',
port=3306,
user='remote',
password='tx_1234abc',
db='Jefrey',
charset='utf8mb4',
autocommit = True, #新增
cursorclass=pymysql.cursors.DictCursor,
)
while True:
with connection.cursor() as cursor:
# Create a new record
sql = " select * from users WHERE email=%s"
# sql = "INSERT INTO `users` (`email`, `password`) VALUES (%s, %s)"
rows_count = cursor.execute(sql, ('webmaster@python.org'))
result = cursor.fetchall()
print(result)
# connection.commit()
time.sleep(1)
打印输出,可以查到新更新的数据:
()
()
[{u'password': u'test', u'id': 340, u'email': u'webmaster@python.org'}]
[{u'password': u'test', u'id': 340, u'email': u'webmaster@python.org'}]
[{u'password': u'test', u'id': 340, u'email': u'webmaster@python.org'}, {u'password': u'test', u'id': 341, u'email': u'webmaster@python.org'}]
② 修改事务隔离级别(具体级别详情下面介绍)
设置隔离级别命令 set [global/session] transaction isolation level xxxx; 如果使用global则修改的是数据库的默认隔离级别,所有新开的窗口的隔离级别继承自这个默认隔离级别如果使用session修改,则修改的是当前客户端的隔离级别,和数据库默认隔离级别无关。当前的客户端是什么隔离级别,就能防止什么隔离级别问题,和其他客户端是什么隔离级别无关。
# 设置事务隔离级别
mysql> set global transaction isolation level READ COMMITTED;
Query OK, 0 rows affected (0.00 sec)
mysql> exit
Bye
[root@localhost ~]# mysql
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 130
Server version: 5.6.36 MySQL Community Server (GPL) Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+
此时用最刚刚开始的代码查询,即使不更新事务依然可以查的到新添加的数据,打印输出,可以查到新更新的数据:
()
()
[{u'password': u'test', u'id': 340, u'email': u'webmaster@python.org'}]
[{u'password': u'test', u'id': 340, u'email': u'webmaster@python.org'}]
[{u'password': u'test', u'id': 340, u'email': u'webmaster@python.org'}, {u'password': u'test', u'id': 341, u'email': u'webmaster@python.org'}]
③ 关闭数据库的事务(修改存储引擎)
# 查看存储引擎
mysql> show create table users;
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| users | CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(255) COLLATE utf8_bin NOT NULL,
`password` varchar(255) COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=350 DEFAULT CHARSET=utf8 COLLATE=utf8_bin |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec) # 修改为MyISAM
mysql> alter table users engine = MyISAM;
Query OK, 5 rows affected (0.02 sec)
Records: 5 Duplicates: 0 Warnings: 0 # 再次查看存储引擎
mysql> show create table users;
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| users | CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(255) COLLATE utf8_bin NOT NULL,
`password` varchar(255) COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=350 DEFAULT CHARSET=utf8 COLLATE=utf8_bin |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
再次用最刚刚开始的代码查询,此时跟事务已经没有什么关系了,可以查的到新添加的数据
()
()
[{u'password': u'test', u'id': 340, u'email': u'webmaster@python.org'}]
[{u'password': u'test', u'id': 340, u'email': u'webmaster@python.org'}]
[{u'password': u'test', u'id': 340, u'email': u'webmaster@python.org'}, {u'password': u'test', u'id': 341, u'email': u'webmaster@python.org'}]
数据库事务:
事务指逻辑上的一组操作,组成这组操作的各个单元,要不全部成功,要不全部不成功
事务特性:
- 原子性(Atomicity):原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
- 一致性(Consistency):事务前后数据的完整性必须保持一致。在事务执行之前数据库是符合数据完整性约束的,无论事务是否执行成功,事务结束后的数据库中的数据也应该是符合完整性约束的。在某一时间点,如果数据库中的所有记录都能保证满足当前数据库中的所有约束,则可以说当前的数据库是符合数据完整性约束的。比如删部门表前应该删掉关联员工(已经建立外键),如果数据库服务器发生错误,有一个员工没删掉,那么此时员工的部门表已经删除,那么就不符合完整性约束了,所以这样的数据库也就性能太差啦!
- 隔离性(Isolation):事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。
- 持久性(Durability):持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
隔离性:
将数据库设计为串行化程的数据库,让一张表在同一时间内只能有一个线程来操作。如果将数据库设计为这样,那数据库的效率太低了。所以数据库的设计这没有直接将数据库设计为串行化,而是为数据库提供多个隔离级别选项,使数据库的使用者可以根据使用情况自己定义到底需要什么样的隔离级别。
脏读:
一个事务读取到了另一个事务未提交的数据,这是特别危险的,要尽力防止。
a 1000
b 1000
a:
start transaction;
update set money=money+100 where name=b;
b:
start transaction;
select * from account where name=b;--1100
commit;
a:
rollback;
b: start transaction;
select * from account where name=b;--1000
不可重复读(开题遇到的问题就是此项):
在一个事务内读取表中的某一行数据,多次读取结果不同。(一个事务读取到了另一个事务已经提交的数据--增加记录、删除记录、修改记录),在某写情况下并不是问题,在另一些情况下就是问题。 a:
start transaction;
select 活期账户 from account where name=b;--1000 活期账户:1000
select 定期账户 from account where name=b;--1000 定期账户:1000
select 固定资产 from account where name=b;--1000 固定资产:1000
------------------------------
b:
start transaction;
update set money=0 where name=b;
commit;
------------------------------
select 活期+定期+固定 from account where name=b; --2000 总资产: 2000
虚读:
是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。(一个事务读取到了另一个事务已经提交的数据---增加记录、删除记录),在某写情况下并不是问题,在另一些情况下就是问题。 b 1000
c 2000
d 3000
a:
start transaction
select sum(money) from account;---3000 3000
-------------------
d:start transaction;
insert into account values(d,3000);
commit;
-------------------
select count(*)from account;---3 3
3000/3 = 1000 1000
四个隔离级别
Read Uncommitted(读取未提交内容):
所有事务都可以看到其他未提交事务的执行结果
本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少
该级别引发的问题是——脏读(Dirty Read):读取到了未提交的数据
#首先,修改隔离级别
set tx_isolation='READ-UNCOMMITTED';
select @@tx_isolation;
+------------------+
| @@tx_isolation |
+------------------+
| READ-UNCOMMITTED |
+------------------+ #事务A:启动一个事务
start transaction;
select * from tx;
+------+------+
| id | num |
+------+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
+------+------+ #事务B:也启动一个事务(那么两个事务交叉了)
在事务B中执行更新语句,且不提交
start transaction;
update tx set num=10 where id=1;
select * from tx;
+------+------+
| id | num |
+------+------+
| 1 | 10 |
| 2 | 2 |
| 3 | 3 |
+------+------+ #事务A:那么这时候事务A能看到这个更新了的数据吗?
select * from tx;
+------+------+
| id | num |
+------+------+
| 1 | 10 | --->可以看到!说明我们读到了事务B还没有提交的数据
| 2 | 2 |
| 3 | 3 |
+------+------+ #事务B:事务B回滚,仍然未提交
rollback;
select * from tx;
+------+------+
| id | num |
+------+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
+------+------+ #事务A:在事务A里面看到的也是B没有提交的数据
select * from tx;
+------+------+
| id | num |
+------+------+
| 1 | 1 | --->脏读意味着我在这个事务中(A中),事务B虽然没有提交,但它任何一条数据变化,我都可以看到!
| 2 | 2 |
| 3 | 3 |
+------+------+
READ-UNCOMMITTED
Read Committed(读取提交内容):
这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)
它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变
这种隔离级别出现的问题是——不可重复读(Nonrepeatable Read):不可重复读意味着我们在同一个事务中执行完全相同的select语句时可能看到不一样的结果。
导致这种情况的原因可能有:(1)有一个交叉的事务有新的commit,导致了数据的改变;(2)一个数据库被多个实例操作时,同一事务的其他实例在该实例处理其间可能会有新的
#首先修改隔离级别
set tx_isolation='read-committed';
select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+ #事务A:启动一个事务
start transaction;
select * from tx;
+------+------+
| id | num |
+------+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
+------+------+ #事务B:也启动一个事务(那么两个事务交叉了)
在这事务中更新数据,且未提交
start transaction;
update tx set num=10 where id=1;
select * from tx;
+------+------+
| id | num |
+------+------+
| 1 | 10 |
| 2 | 2 |
| 3 | 3 |
+------+------+ #事务A:这个时候我们在事务A中能看到数据的变化吗?
select * from tx; --------------->
+------+------+ |
| id | num | |
+------+------+ |
| 1 | 1 |--->并不能看到! |
| 2 | 2 | |
| 3 | 3 | |
+------+------+ |——>相同的select语句,结果却不一样
|
#事务B:如果提交了事务B呢? |
commit; |
|
#事务A: |
select * from tx; --------------->
+------+------+
| id | num |
+------+------+
| 1 | 10 |--->因为事务B已经提交了,所以在A中我们看到了数据变化
| 2 | 2 |
| 3 | 3 |
+------+------+
READ-COMMITTED
Repeatable Read(可重读):
这是MySQL的默认事务隔离级别
它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行
此级别可能出现的问题——幻读(Phantom Read):当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行
InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题
#首先,更改隔离级别
set tx_isolation='repeatable-read';
select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+ #事务A:启动一个事务
start transaction;
select * from tx;
+------+------+
| id | num |
+------+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
+------+------+ #事务B:开启一个新事务(那么这两个事务交叉了)
在事务B中更新数据,并提交
start transaction;
update tx set num=10 where id=1;
select * from tx;
+------+------+
| id | num |
+------+------+
| 1 | 10 |
| 2 | 2 |
| 3 | 3 |
+------+------+
commit; #事务A:这时候即使事务B已经提交了,但A能不能看到数据变化?
select * from tx;
+------+------+
| id | num |
+------+------+
| 1 | 1 | --->还是看不到的!(这个级别2不一样,也说明级别3解决了不可重复读问题)
| 2 | 2 |
| 3 | 3 |
+------+------+ #事务A:只有当事务A也提交了,它才能够看到数据变化
commit;
select * from tx;
+------+------+
| id | num |
+------+------+
| 1 | 10 |
| 2 | 2 |
| 3 | 3 |
+------+------+
REPEATABLE-READ
Serializable(可串行化):
这是最高的隔离级别
它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。
在这个级别,可能导致大量的超时现象和锁竞争
#首先修改隔离界别
set tx_isolation='serializable';
select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| SERIALIZABLE |
+----------------+ #事务A:开启一个新事务
start transaction; #事务B:在A没有commit之前,这个交叉事务是不能更改数据的
start transaction;
insert tx values('4','4');
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
update tx set num=10 where id=1;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
SERIALIZABLE
注:
安全性考虑:Serializable>Repeatable read>Read committed>Read uncommitted
数据库效率:Read uncommitted>Read committed>Repeatable read>Serializable
一般情况下,我们会使用Repeatable read、Read committed mysql数据库默认的数据库隔离级别Repeatable read
转自:https://www.bkjia.com/Pythonjc/1228355.html
解决pymysql不能实时查询最新的数据的更多相关文章
- oracle 中从一个历史表中查询最新日期数据插入到另一个表中语句
先从历史表中查询最新的一个语句: select t.id from ( select r.*, row_number() over(partition by r.分组字段 order by r.排序时 ...
- [SQL]查询最新的数据
在设计数据库的时候,把数据的跟新,删除都是软操作,就是都是变成了增加,也是会需要读取最新的那条数据 ' 获取最新时间的数据 Select a.* FROM SortInfo a,(SELECT SnS ...
- mysql更新数据,条件为实时查询出来的数据
--将更新条件保存到临时表里 CREATE TABLE tmp3 AS (SELECT username FROM oa_user WHERE username NOT IN (SELECT user ...
- mysql查询最新一组数据
public function getDetail(){ $sql = "SELECT * FROM (SELECT * FROM Z_CFTC_GOV_NEW ORDER BY UPDAT ...
- Druid:一个用于大数据实时处理的开源分布式系统——大数据实时查询和分析的高容错、高性能开源分布式系统
转自:http://www.36dsj.com/archives/28590 Druid 是一个用于大数据实时查询和分析的高容错.高性能开源分布式系统,旨在快速处理大规模的数据,并能够实现快速查询和分 ...
- Android网络开发之实时获取最新数据
在实际开发中更多的是需要我们实时获取最新数据,比如道路流量.实时天气信息等,这时就需要通过一个线程来控制视图的更新. 示例:我们首先创建一个网页来显示系统当前的时间,然后在Android程序中每隔5秒 ...
- 基于py3和pymysql的数据库查询,查询某几列的数据
#python3 #xiaodeng #基于py3和pymysql的数据库查询,查询某几列的数据 import pymysql conn=pymysql.connect(....) cur=conn. ...
- Impala简介PB级大数据实时查询分析引擎
1.Impala简介 • Cloudera公司推出,提供对HDFS.Hbase数据的高性能.低延迟的交互式SQL查询功能. • 基于Hive使用内存计算,兼顾数据仓库.具有实时.批处理.多并发等优点 ...
- (转)解决mybatis的mapper.xml查询不出数据,结果一直为null问题
背景:记录mybatis使用过程中遇到的相关问题. 解决mybatis的mapper.xml查询不出数据,结果一直为null问题 解决方案: 1 修改实体类与数据库字段名相同 2 修改sql查询语句, ...
随机推荐
- 报错:Program bash is not found in PATH
(如果按照我的方法来的话是没有这个错误的,我之前用别的方法的时候有但是后来还是没解决,写出来放到这里做参考吧) 参考原文:http://blog.csdn.net/fuyongbing1986/art ...
- Notification高级技巧
观察Notification这个类,你会发现里面还有很多我们没有使用过的属性.先来看看sound这个属性吧,它可以在通知发出的时候播放一段音频,这样就能够更好地告知用户有通知到来.sound 这个属性 ...
- springMvc-reset风格和对静态资源的管理
1.所谓rest风格及比较优雅的,没有一大堆后缀的风格 2.对静态资源的管理,及样式.图片等不需要springMvc过滤 代码: 1.在springMvc的配置文件中添加mvc标签 <?xml ...
- oracle数据类型及操作
1. Oracle字符串操作 1.1 字符串类型 Ø CHAR和VARCHAR2类型 l CHAR存放定长字符,如果数据存不满指定长度则用空格补齐,CHAR类型浪费空间换取查询时间的缩短. l VAR ...
- 基于PowerShell的Lync Server管理 使用C# 之 Telephony 功能 查看 /修改
本以为这个属性可以在用户信息中直接反应出来,但是看了好几遍还是没找到这个属性名称 这个功能没有在get-User 的结果中直接反映出来 但是可以通过 Property 查找单个选项 如: Get-Cs ...
- 在vue-cli中使用路由
1.首先npm中是否有vue-router 一般在vue-cli的时候就已经下载好了依赖包了 2.使用vue的话正常的需要涉及这几个文件 demo/src/router/index.js import ...
- 2017.12.25 Java中面向对象思想的深刻理解
今日内容介绍 1.面向对象思想 2.类与对象的关系 3.局部变量和成员变量的关系 4.封装思想 5.private,this关键字 6.随机点名器 01面向对象和面向过程的思想 * A: 面向过程与面 ...
- python基础一 day17 初识递归
#递归函数 # 了解什么是递归 : 在函数中调用自身函数 # 最大递归深度默认是997/998 —— 是python从内存角度出发做得限制 # 能看懂递归 # 能知道递归的应用场景 # 初识递归 —— ...
- HTML 5.1 的 14 个新特性(含使用案例)
HTML5 属于万维网联盟 (W3C), 这个组织为整个网络界提供了标准,如此形成的协议可在全世界通行.在 2016 年 11 月, W3C 对长期行使的 HTML 5 标准进行了更新,它是2年内的第 ...
- Web/Java Web项目如何模块化?没有正文,别点
事情是这样的,两三年前做了几个Java Web项目,由于薪资原因,原主程都离开了. 由于公司不规范,也没有留下正规的开发文档,只有一个源程序在手里.后面的很多系统维护都很被动. 领导就觉得说,这样不好 ...