一个线上SQL执行顺序和结果的定位排查工具

该博客介绍了如何使用工具解析网络包中的SQL执行语句和结果。通过golang安装的`mysql-replay`工具,可以实时分析生产环境网络包或本地pcap文件。工具支持TCPDump抓包,然后解析出SQL查询、建立连接、关闭连接等信息,便于检查SQL执行顺序和结果的准确性。

安装工具

功能: 读取生产环境的网络包或者 pcap 包文件,并解析网络包中的SQL执行语句和执行结果保存到本地

go install github.com/ssoor/mysql-replay@latest

使用方式

1. 生产环境实时分析

通过下面语句抓取网卡 ens37 上的网络包并解析SQL执行语句和执行结果,最终结果会输出到控制台和文件 output/mysql_events.json

mysql-replay online replay --device=ens37 --srcPort=30696

2 生产环境抓包,本地分析

2.1 抓取生产环境的网络包

执行下面语句抓取网络包并存储在 pcaps/ens37.pcap 文件中

下面的命令指定了在网卡 ens37 上抓取协议为 tcp 并且端口为 3306 的网络包存储在 pcaps/ens37.pcap 文件中,具体参数可以查 tcpdump 的使用说明

tcpdump -i ens37 -w pcaps/ens37.pcap tcp and port 3306

2.2 解析网络包中的SQL执行语句和执行结果

通过下面语句解析网络包文件 ./pcaps/mysql.pcap 中的SQL执行语句和执行结果,最终结果会输出到控制台和文件 output/mysql_events.json

mysql-replay text replay --srcPort=3306 ./pcaps/mysql.pcap

3 检查SQL执行顺序和结果是否正确

最终结果输出格式如下:

{
    "02e6266c799050c1": [
        {
            "conn": {
                "dst": "192.168.4.198:3306",
                "src": "192.168.4.195:56398"
            },
            "time": 1652943125032441000,
            "type": "handshake",
            "db": "config_test",
            "username": "jn_cn",
            "packet_res": []
        },
        {
            "conn": {
                "dst": "192.168.4.198:3306",
                "src": "192.168.4.195:56398"
            },
            "time": 1652943125033208000,
            "type": "query",
            "query": "SET NAMES 'utf8'",
            "packet_res": []
        },
        {
            "conn": {
                "dst": "192.168.4.198:3306",
                "src": "192.168.4.195:56398"
            },
            "time": 1652943125033595000,
            "type": "query",
            "query": "SELECT * FROM `functionupgrade` WHERE (`organizationId`='39fd9286-f365-1620-574a-e4b7eb1a58ae') AND (`functionName`='禁用转介')",
            "packet_res": []
        },
        {
            "conn": {
                "dst": "192.168.4.198:3306",
                "src": "192.168.4.195:56398"
            },
            "time": 1652943125084277000,
            "type": "query",
            "query": "SELECT * FROM `p_mini_program` WHERE `mini_app_id`='wxefe5a0c8c09'",
            "packet_res": [
                {
                    "application_code": "5032",
                    "created_by": "400",
                    "created_on": "2021-11-12 11:33:19",
                    "id": "3a002461-c89c-fccd-c8ed-36511de5ad1e",
                    "mini_app_id": "wxefe5a0c8c09",
                    "modified_by": "400",
                    "modified_on": "2021-11-12 11:33:19",
                    "subject_id": "lojwvr162868"
                }
            ]
        }
    ],
    "0735d71670b4ef5e": [
        {
            "conn": {
                "dst": "192.168.4.198:3306",
                "src": "192.168.4.195:56082"
            },
            "time": 1652943122225499000,
            "type": "handshake",
            "db": "config_test",
            "username": "jtuan_cn",
            "packet_res": []
        },
        {
            "conn": {
                "dst": "192.168.4.198:3306",
                "src": "192.168.4.195:56082"
            },
            "time": 1652943122230773000,
            "type": "query",
            "query": "SET NAMES 'utf8'",
            "packet_res": []
        },
        {
            "conn": {
                "dst": "192.168.4.198:3306",
                "src": "192.168.4.195:56082"
            },
            "time": 1652943122233428000,
            "type": "query",
            "query": "SELECT * FROM `import_task` WHERE `status`=1 ORDER BY `created_on`",
            "packet_res": []
        },
        {
            "conn": {
                "dst": "192.168.4.198:3306",
                "src": "192.168.4.195:56082"
            },
            "time": 1652943122241219000,
            "type": "quit",
            "packet_res": []
        }
    ]
}

具体含义如下:

{
    "连接ID": [
        {
            "conn": {
                "dst": "连接目标地址",
                "src": "连接来源地址"
            },
            "type": "SQL类型",
            "time": "SQL发生时间",
            "db": "使用的数据库",
            "username": "登录使用的用户名",
            "query": "执行的SQL语句",
            "stmtID": "预解析语句ID",
            "package_res": "SQL执行的结果"
        }
    ]
}

SQL类型:

  • handshake=建立连接
  • query=执行SQL查询
  • stmt_prepare=预解析语句
  • stmt_execute=执行预解析语句
  • stmt_close=删除预解析语句
  • quit=关闭连接
### 线上系统锁表问题排查方法与数据库锁定解决方案 #### 1. 锁表问题的定义与影响 锁表问题通常发生在数据库中,当一个事务长时间持有锁而未释放时,会导致其他事务无法访问相关资源。这种现象可能会引起系统性能下降、请求超时甚至服务不可用[^4]。 #### 2. 锁表问题的排查步骤 - **确定问题现象**:通过观察系统日志或监控工具,确认是否存在长时间阻塞的情况。例如,可以检查是否有大量SQL语句处于等待状态。 - **收集相关信息**:使用数据库提供的诊断工具获取详细信息。例如,SQL Server可以通过以下命令查看当前的阻塞会话: ```sql SELECT * FROM sys.dm_exec_requests WHERE blocking_session_id > 0; ``` 此外,还可以启用死锁跟踪以捕获详细的锁冲突信息: ```sql DBCC TRACEON (1222, -1); ``` 死锁详情会被记录在SQL Server错误日志中,包含事务ID、SQL语句锁资源[^2]。 - **分析可能原因**:根据收集到的信息,分析哪些事务持有锁且未释放。常见的原因包括: - 长事务未提交或回滚。 - 并发事务对同一资源的加锁顺序不一致[^3]。 - 数据库索引设计不合理,导致锁范围过大。 - **逐步排查**:针对上述可能原因逐一验证。例如,可以通过以下查询找出长时间运行的事务: ```sql SELECT session_id, command, wait_time, blocking_session_id FROM sys.dm_exec_requests WHERE wait_time > 5000; -- 超过5秒的等待 ``` #### 3. 数据库锁定的解决方案 - **优化事务处理**:确保所有事务尽可能短,避免长事务占用锁资源。可以通过减少事务中的操作数量或拆分复杂事务来实现。 - **调整加锁顺序**:如果多个事务需要访问相同的资源,建议统一加锁顺序以减少死锁风险[^3]。 - **改进索引设计**:合理设计索引可以缩小锁的范围,降低锁冲突的概率。例如,为高频更新的列创建覆盖索引。 - **启用行级锁**:对于支持行级锁的数据库(如MySQL InnoDB),尽量避免表级锁,以提高并发性能[^4]。 - **定期清理残留锁**:某些情况下,异常中断可能导致锁未正确释放。可以通过以下命令强制终止会话并释放锁: ```sql KILL <session_id>; ``` #### 4. 示例代码 以下是一个简单的脚本,用于检测解决锁表问题: ```sql -- 查找阻塞会话 SELECT r.session_id, r.blocking_session_id, r.command, r.wait_time, t.text FROM sys.dm_exec_requests r CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t WHERE r.blocking_session_id > 0; -- 强制终止阻塞会话 KILL <blocking_session_id>; ``` #### 5. 验证修复效果 在实施解决方案后,需要通过以下方式验证效果: - 检查系统日志,确认是否仍有锁冲突或阻塞现象。 - 使用性能监控工具,观察系统响应时间吞吐量是否恢复正常。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值