SQL 死锁 Python 数据插入
SQL Deadlock with Python Data Insert
我目前正在尝试使用 python 构建一个数据库接口来存储股票数据。此数据采用元组列表的形式,每个元素由“日期、开盘价、最高价、最低价、收盘价、成交量”组成。date
表示 UNIX 时间戳,并且必须与数据库。下面是典型处理输出的示例 (company_stock
):
[(1489780560, 'NYSE:F', 12.5, 12.505, 12.49, 12.495, 567726),
(1489780620, 'NYSE:F', 12.495, 12.5, 12.48, 12.48, 832487),
(1489780680, 'NYSE:F', 12.485, 12.49, 12.47, 12.475, 649818),
(1489780740, 'NYSE:F', 12.475, 12.48, 12.47, 12.47, 700579),
(1489780800, 'NYSE:F', 12.47, 12.48, 12.47, 12.48, 567798)]
我正在使用 pymysql
包将此列表插入本地 MySQL 数据库(版本 5.5)。当代码 运行 完成并插入值时,数据库将在达到约 250k 行后崩溃 - 或者更确切地说停止。由于相关 这是股票数据处理功能的导出部分,大约每 20 秒调用一次并插入大约 400 个值。
# SQL Export
def tosql(company_stock, ticker, interval, amount_period, period):
try:
conn = pymysql.connect(host = "localhost", user = "root",
passwd = "pw", db = "db", charset = "utf8",
autocommit = True,
cursorclass = pymysql.cursors.DictCursor)
cur = conn.cursor()
# To temp table
query = "INSERT INTO stockdata_import "
query += "(date, tickersymbol, open, high, low, close, volume)"
query += "VALUES (%s, %s, %s, %s, %s, %s, %s)"
cur.executemany(query, company_stock)
# Duplicate Check with temp table and existing database storage
query = "INSERT INTO stockdata (date, tickersymbol, open, high, low, close, volume) "
query += "SELECT i.date, i.tickersymbol, i.open, i.high, i.low, "
query += "i.close, i.volume FROM stockdata_import i "
query += "WHERE NOT EXISTS(SELECT dv.date, dv.tickersymbol FROM "
query += "stockdata dv WHERE dv.date = i.date "
query += "AND dv.tickersymbol = i.tickersymbol)"
cur.execute(query)
print(": ".join([datetime.now().strftime("%d.%m.%Y %H:%M:%S"),
"Data stored in Vault. Ticker", str(ticker),
"Interval", str(interval),
"Last", str(amount_period), str(period)]))
finally:
# Clear temp import table and close connection
query = "DELETE from stockdata_import"
cur.execute(query)
cur.close()
conn.close()
我怀疑随着数据库的增长检查已经存在的值花费的时间太长,最终由于检查 [=55= 的唯一性时 tables (?) 的锁定而崩溃] 组合。因为我希望这个数据库增长得相当快(每周大约 100 万行),所以似乎需要一个不同的解决方案来确保只有一个 date/ticker 对。这是导入 table 的 SQL CREATE
语句(与之比较的真实 table 看起来是一样的):
CREATE TABLE stockdata_import (id_stock_imp BIGINT(12) NOT NULL AUTO_INCREMENT,
date INT(10),
tickersymbol VARCHAR(16),
open FLOAT(12,4),
high FLOAT(12,4),
low FLOAT(12,4),
close FLOAT(12,4),
volume INT(12),
crawled_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(id_stock_imp));
我已经研究过为 date
/tickersymbol
对设置约束并处理 python 中即将发生的异常,但到目前为止我的研究表明这将是均匀的更慢加上我什至不确定这是否适用于 pymysql
游标函数 executemany(query, data)
.
的批量插入
上下文信息:
- 上面显示的 SQL 导出是处理股票数据响应的 python 脚本的最后一部分。反过来,这个脚本被另一个脚本调用,该脚本由 crontab 定时为每天特定时间运行。
- 一旦 crontab 启动控制脚本,这将调用下标约 500 次,每次 运行 之间的休眠时间约为 20-25 秒。
- 我在日志中看到的错误是:ERROR 1205 (HY000): Lock wait timeout exceeded;尝试重新启动事务
问题:
- 如何优化查询或更改存储 table 以确保给定
date
/ticker
组合的唯一性?
- 这就是问题所在,还是我在这里没有看到其他问题?
- 也欢迎任何进一步的建议。
如果您想确保数据的唯一性,只需在相关的date
和ticker
字段上添加一个unique 索引即可。唯一索引防止插入重复值,因此插入前无需检查数据是否存在。
既然不想插入重复数据,就用insert ignore代替plain insert来抑制重复插入错误。根据受影响的行数,您仍然可以检测并记录重复插入。
我目前正在尝试使用 python 构建一个数据库接口来存储股票数据。此数据采用元组列表的形式,每个元素由“日期、开盘价、最高价、最低价、收盘价、成交量”组成。date
表示 UNIX 时间戳,并且必须与数据库。下面是典型处理输出的示例 (company_stock
):
[(1489780560, 'NYSE:F', 12.5, 12.505, 12.49, 12.495, 567726),
(1489780620, 'NYSE:F', 12.495, 12.5, 12.48, 12.48, 832487),
(1489780680, 'NYSE:F', 12.485, 12.49, 12.47, 12.475, 649818),
(1489780740, 'NYSE:F', 12.475, 12.48, 12.47, 12.47, 700579),
(1489780800, 'NYSE:F', 12.47, 12.48, 12.47, 12.48, 567798)]
我正在使用 pymysql
包将此列表插入本地 MySQL 数据库(版本 5.5)。当代码 运行 完成并插入值时,数据库将在达到约 250k 行后崩溃 - 或者更确切地说停止。由于相关 这是股票数据处理功能的导出部分,大约每 20 秒调用一次并插入大约 400 个值。
# SQL Export
def tosql(company_stock, ticker, interval, amount_period, period):
try:
conn = pymysql.connect(host = "localhost", user = "root",
passwd = "pw", db = "db", charset = "utf8",
autocommit = True,
cursorclass = pymysql.cursors.DictCursor)
cur = conn.cursor()
# To temp table
query = "INSERT INTO stockdata_import "
query += "(date, tickersymbol, open, high, low, close, volume)"
query += "VALUES (%s, %s, %s, %s, %s, %s, %s)"
cur.executemany(query, company_stock)
# Duplicate Check with temp table and existing database storage
query = "INSERT INTO stockdata (date, tickersymbol, open, high, low, close, volume) "
query += "SELECT i.date, i.tickersymbol, i.open, i.high, i.low, "
query += "i.close, i.volume FROM stockdata_import i "
query += "WHERE NOT EXISTS(SELECT dv.date, dv.tickersymbol FROM "
query += "stockdata dv WHERE dv.date = i.date "
query += "AND dv.tickersymbol = i.tickersymbol)"
cur.execute(query)
print(": ".join([datetime.now().strftime("%d.%m.%Y %H:%M:%S"),
"Data stored in Vault. Ticker", str(ticker),
"Interval", str(interval),
"Last", str(amount_period), str(period)]))
finally:
# Clear temp import table and close connection
query = "DELETE from stockdata_import"
cur.execute(query)
cur.close()
conn.close()
我怀疑随着数据库的增长检查已经存在的值花费的时间太长,最终由于检查 [=55= 的唯一性时 tables (?) 的锁定而崩溃] 组合。因为我希望这个数据库增长得相当快(每周大约 100 万行),所以似乎需要一个不同的解决方案来确保只有一个 date/ticker 对。这是导入 table 的 SQL CREATE
语句(与之比较的真实 table 看起来是一样的):
CREATE TABLE stockdata_import (id_stock_imp BIGINT(12) NOT NULL AUTO_INCREMENT,
date INT(10),
tickersymbol VARCHAR(16),
open FLOAT(12,4),
high FLOAT(12,4),
low FLOAT(12,4),
close FLOAT(12,4),
volume INT(12),
crawled_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(id_stock_imp));
我已经研究过为 date
/tickersymbol
对设置约束并处理 python 中即将发生的异常,但到目前为止我的研究表明这将是均匀的更慢加上我什至不确定这是否适用于 pymysql
游标函数 executemany(query, data)
.
上下文信息:
- 上面显示的 SQL 导出是处理股票数据响应的 python 脚本的最后一部分。反过来,这个脚本被另一个脚本调用,该脚本由 crontab 定时为每天特定时间运行。
- 一旦 crontab 启动控制脚本,这将调用下标约 500 次,每次 运行 之间的休眠时间约为 20-25 秒。
- 我在日志中看到的错误是:ERROR 1205 (HY000): Lock wait timeout exceeded;尝试重新启动事务
问题:
- 如何优化查询或更改存储 table 以确保给定
date
/ticker
组合的唯一性? - 这就是问题所在,还是我在这里没有看到其他问题?
- 也欢迎任何进一步的建议。
如果您想确保数据的唯一性,只需在相关的date
和ticker
字段上添加一个unique 索引即可。唯一索引防止插入重复值,因此插入前无需检查数据是否存在。
既然不想插入重复数据,就用insert ignore代替plain insert来抑制重复插入错误。根据受影响的行数,您仍然可以检测并记录重复插入。