Python3 操作 MySQL 时遇到数据更新问题如何解决?

最近尝试用 Python3 写一个简单的爬虫程序,后端使用 MySQL 存储爬取的一些数据,其中定义了一张 URLs 表,表结构很简单,如下:
| id | url | flag |
|----|----|-----|
程序逻辑是先抓取一定量的 URL 存到 URLs 表中,然后每次取一条 URL 进行处理,处理完之后就更新 URLs 表中对应的记录。其中 flag 列就是用来标识该 URL 是否已经经过处理,列的值用 YES/NO 表示。 相关代码如下:

def crawler_controller(entry):  
  # 连接数据库
  connection = mysql.connector.connect(user='mysql', password='mysql', database='crawler_db')  
  # 创建游标
  cursor = connection.cursor()  
  # 无限循环,直到从数据库取出的记录为空
  while True:  
    # 从数据库取出一条 flag 标记为 NO 的记录
    sql_select_recored = "SELECT * FROM urls WHERE flag='NO' LIMIT 1"  
    cursor.execute(sql_select_recored)  
    get_values = cursor.fetchall()  
# 判断该记录是否存在数据
if get_values:  
  # 处理相应的 url
  url_parser(get_values)  
  # 更新已处理的记录,反复测试过,就是这一条出了问题,始终不能更新数据库记录  
  cursor.execute("UPDATE urls SET flag='YES' WHERE id='%s'", get_values[0][0])  
  # 完成处理
  connection.commit()
  cursor.close()
else  
  break

关闭数据库连接

connection.close()

现在的问题是,调用 url_parser(get_values)函数处理完 URL 之后,接下来的更新数据库记录死活不能生效,按道理说 get_values[0][0]的值就是对应的记录 id ,而且直接在数据库的 CLI 下面,用

UPDATE urls SET flag='YES' WHERE id='1'  

测试,这样又是可以更新记录的。
还望有经验的老司机们指点一二。


Python3 操作 MySQL 时遇到数据更新问题如何解决?

6 回复

事务锁吧,干脆用消息队列好了。


遇到MySQL数据更新问题,先检查这几个关键点:

1. 确认连接和事务

import pymysql

# 确保autocommit设置正确
conn = pymysql.connect(
    host='localhost',
    user='root',
    password='your_password',
    database='test_db',
    autocommit=True  # 自动提交事务
)

# 或者手动控制事务
try:
    with conn.cursor() as cursor:
        sql = "UPDATE users SET name=%s WHERE id=%s"
        cursor.execute(sql, ('new_name', 1))
    conn.commit()  # 必须提交!
except Exception as e:
    conn.rollback()
    print(f"更新失败: {e}")
finally:
    conn.close()

2. 检查WHERE条件 最常见的问题是WHERE条件不匹配导致0行更新:

# 先查询确认数据存在
cursor.execute("SELECT * FROM users WHERE id=%s", (1,))
result = cursor.fetchone()
if result:
    # 执行更新
    cursor.execute("UPDATE users SET status='active' WHERE id=%s", (1,))
else:
    print("目标记录不存在")

3. 数据类型匹配 确保传入参数类型与数据库字段类型一致:

# 错误示例:字符串传给整型字段
cursor.execute("UPDATE products SET stock=%s WHERE id=%s", ('100', 1))  # stock是INT字段

# 正确做法
cursor.execute("UPDATE products SET stock=%s WHERE id=%s", (100, 1))

4. 完整示例

def update_user_email(user_id, new_email):
    conn = pymysql.connect(host='localhost', user='root', 
                          password='pass', database='mydb')
    try:
        with conn.cursor() as cursor:
            # 检查用户是否存在
            cursor.execute("SELECT id FROM users WHERE id=%s", (user_id,))
            if not cursor.fetchone():
                return False
            
            # 执行更新
            affected = cursor.execute(
                "UPDATE users SET email=%s WHERE id=%s",
                (new_email, user_id)
            )
            
            if affected == 0:
                print("更新了0行,可能数据未变化")
            
        conn.commit()
        return True
        
    except pymysql.Error as e:
        print(f"数据库错误: {e}")
        conn.rollback()
        return False
    finally:
        conn.close()

排查顺序:先看事务提交,再查WHERE条件,最后核数据格式。

print get_values[0][0] 下看看就知道了
理论上应该是空?
get_values[0] 试试 print 这个能否输出数据库的 id 字段

+1 ,打印 get_values[0][0] 看看顺序是否你预期的

btw, 既然都 limit 1 了,干嘛还用 fetchall ,直接用 fetchone 不就得了

是不是可以 dict cursor

建议 select 语句取出所需的列而不是用*,这样可以预计所需 id 的 key 。不过这样的处理还是推荐多线程然后使用队列来操作 MySQL 。

回到顶部