欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python 操作数据库 MySQL

程序员文章站 2024-03-21 20:51:10
...

当用 Python 操作MySQL时,我们经常用的驱动是 mysql.connector

import mysql.connector
from mysql.connector import InterfaceError, OperationalError

这里需要强调的是:

  1. 如果 SQL 执行的是 ALTER 操作,则当客户端程序走到 cursor.execute(sql) 后:
    如果因为 SQL 返回超时,客户端抛异常然后close cursor 和 conn 最后程序结束。

    此时登录数据库服务器, 执行 show processlist 可以看到连接还存在了也就是 SQL 还在数据库服务端执行中。随着时间推移,大多数情况该 ALTER SQL 都能执行成功。这需要特别注意:客户端都异常退出了,SQL 还在服务端执行,最后还能执行成功,但是仅仅限于 DDL,因为其他类的 SQL 需要客户端的 commit 或者接受数据
    如果想改变这种行为,可以在客户端捕获异常后,快速建立一个新连接把这个连接 KILL 掉。

  2. 模拟 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> 
    
  3. 当客户端发起的 SQL 在执行时,登录数据库手动 KILL 连接:客户端抛的异常是
    mysql.connector.errors.InterfaceError

  4. 数据库 SQL 执行超时,客户端抛的异常是: mysql.connector.errors.OperationalError

相关标签: MySQL Python