在并行执行MySQL SELECT * 查询

4
我有一个多线程应用程序,定期获取MySQL表的全部内容(使用SELECT * FROM查询)。该应用程序是用Python编写的,使用线程模块进行多线程,并使用mysql-python(mysqldb)作为MySQL驱动程序(使用mysqlalchemy作为包装器会产生类似的结果)。我在MySQL数据库中使用InnoDB引擎。我编写了一个简单的测试来检查并发执行SELECT *查询的性能,并发现所有这些查询都是按顺序实现的。虽然明确将隔离级别设置为READ UNCOMMITTED,但似乎并没有提高性能。
下面是进行DB调用的代码片段:
@ performance.profile() def test_select_all_raw_sql(conn_pool, queue): ''' conn_pool - 从中获取mysql连接的连接池 queue - 任务队列 ''' query = '''SELECT * FROM table''' try: conn = conn_pool.connect() cursor = conn.cursor() cursor.execute("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED") # 执行操作直至队列为空(抛出Queue.Empty) while True: id = queue.get_nowait() cursor.execute(query) result = cursor.fetchall() except Queue.Empty: pass finally: cursor.execute("SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ") conn.close()
我是否正确地期望此查询以并行方式执行?如果是,我该如何在Python中实现它?

我不完全明白你为什么关心数据库如何执行查询。结果必须被序列化以返回给应用程序。 - Gordon Linoff
我很在意这个问题,因为如果数据库在执行时锁定整个表格,它会影响所有并行执行的其他查询,从而影响使用该数据库的服务的性能。 - Sergey
1个回答

1
MySQL允许单个用户或多个用户进行多个连接。在一个连接中,它最多使用一个CPU核心并一次执行一个SQL语句。
“事务”可以由多个SQL语句组成,同时将该事务视为原子性。考虑经典的银行应用程序:
BEGIN;
UPDATE ...  -- decrement from one user's bank balance.
UPDATE ...  -- increment another user's balance.
COMMIT;

这些语句按顺序执行(在单个连接中);它们要么全部成功,要么全部作为一个单元失败(“原子性”)。
如果你需要并行处理,要有一个客户端(或多个客户端),可以运行多个线程(或进程),并且每个线程都要建立自己的MySQL连接。
一个小例外:有一些额外的线程“在幕后”执行后台任务,比如预读、延迟写入或刷新等。但这并不能让用户在单个连接中“同时做两件事”。
我在这里说的适用于所有版本的MySQL/MariaDB和所有访问它们的客户端软件包。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接