Python 操作数据库 MySQL
程序员文章站
2024-03-21 20:51:10
...
当用 Python 操作MySQL时,我们经常用的驱动是 mysql.connector
import mysql.connector
from mysql.connector import InterfaceError, OperationalError
这里需要强调的是:
-
如果 SQL 执行的是 ALTER 操作,则当客户端程序走到 cursor.execute(sql) 后:
如果因为 SQL 返回超时,客户端抛异常然后close cursor 和 conn 最后程序结束。此时登录数据库服务器, 执行 show processlist 可以看到连接还存在了也就是 SQL 还在数据库服务端执行中。随着时间推移,大多数情况该 ALTER SQL 都能执行成功。这需要特别注意:客户端都异常退出了,SQL 还在服务端执行,最后还能执行成功,但是仅仅限于 DDL,因为其他类的 SQL 需要客户端的 commit 或者接受数据。
如果想改变这种行为,可以在客户端捕获异常后,快速建立一个新连接把这个连接 KILL 掉。 -
模拟 ALTER 超时:
1. 在 console 1: a)用 begin 手动开启事务 b) select * from sql_exec_record_dbg limit 1 2. 在 console 2: python alter_poc.py 来变更 sql_exec_record_dbg 的列,同时设置超时时间 10s 3. 在 console1: a) show processlist 可以看到,连接已经打过来了,状态是 Waiting for table metadata lock b) 等待大约 10s 让 console 2 的程序超时异常退出 c) 用 commit; 手动提交事务, d) 可以看到状态为 Waiting for table metadata lock 的连接的 SQL 还是会被执行成功的 mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> mysql> select * from sql_exec_record_dbg limit 1 \G *************************** 1. row *************************** id: 2625 task_id: f79a95ae-e0d1-4d6a-88a4-f396da5066ca cluster_name: NULL db_host: 172.25.28.36 db_port: 3307 db_name: arch table_name: NULL sql: SELECT * FROM `tab1` where 1=1 and `created_date` >= '2019-05-10 14:50:08' and `created_date` < '2019-05-11 00:00:00' limit 100 trans_row: 100 status: 1 create_datetime: 2019-05-13 03:35:32.515228 update_datetime: 2019-05-13 03:35:32.786594 std_err: NULL sub_rule_id: 180 parent_rule_id: 5 1 row in set (0.00 sec) mysql> mysql> show processlist; +----------+-----------+--------------------+----------+---------+------+----------+------------------+ | Id | User | Host | db | Command | Time | State | Info | +----------+-----------+--------------------+----------+---------+------+----------+------------------+ | 50923359 | inception | 172.25.28.38:49664 | archiver | Sleep | 1 | | NULL | | 50923433 | inception | 172.25.28.38:50048 | archiver | Query | 0 | starting | show processlist | +----------+-----------+--------------------+----------+---------+------+----------+------------------+ 2 rows in set (0.00 sec) mysql> mysql> show create table sql_exec_record_dbg \G *************************** 1. row *************************** Table: sql_exec_record_dbg Create Table: CREATE TABLE `sql_exec_record_dbg` ( `id` int(11) NOT NULL AUTO_INCREMENT, ...... `sql` varchar(355) COLLATE utf8_bin DEFAULT NULL, `trans_row` int(10) unsigned NOT NULL, ...... ) ENGINE=InnoDB AUTO_INCREMENT=3464769 DEFAULT CHARSET=utf8 COLLATE=utf8_bin 1 row in set (0.00 sec) mysql> mysql> show processlist; +----------+-----------+--------------------+----------+---------+------+---------------------------------+------------------------------------------------------------------------+ | Id | User | Host | db | Command | Time | State | Info | +----------+-----------+--------------------+----------+---------+------+---------------------------------+------------------------------------------------------------------------+ | 50923359 | inception | 172.25.28.38:49664 | archiver | Sleep | 0 | | NULL | | 50923433 | inception | 172.25.28.38:50048 | archiver | Query | 0 | starting | show processlist | | 50923528 | inception | 172.25.28.38:50538 | archiver | Query | 6 | Waiting for table metadata lock | alter table sql_exec_record_dbg change column `sql` `sql` varchar(400) | +----------+-----------+--------------------+----------+---------+------+---------------------------------+------------------------------------------------------------------------+ 3 rows in set (0.00 sec) mysql> mysql> commit; Query OK, 0 rows affected (0.00 sec) mysql> mysql> show create table sql_exec_record_dbg \G *************************** 1. row *************************** Table: sql_exec_record_dbg Create Table: CREATE TABLE `sql_exec_record_dbg` ( `id` int(11) NOT NULL AUTO_INCREMENT, ...... `sql` varchar(400) COLLATE utf8_bin DEFAULT NULL, `trans_row` int(10) unsigned NOT NULL, ...... ) ENGINE=InnoDB AUTO_INCREMENT=3464769 DEFAULT CHARSET=utf8 COLLATE=utf8_bin 1 row in set (0.00 sec) mysql>
-
当客户端发起的 SQL 在执行时,登录数据库手动 KILL 连接:客户端抛的异常是
mysql.connector.errors.InterfaceError -
数据库 SQL 执行超时,客户端抛的异常是: mysql.connector.errors.OperationalError