美文网首页
update 锁表经验分享(2)

update 锁表经验分享(2)

作者: 燃英 | 来源:发表于2019-05-14 20:02 被阅读0次

    很多情况下慢SQL会导致数据库锁表甚至服务器宕机。

    如果一个线程开启了一个事务,然后执行了一条慢SQL,这就意味着在它执行结束前,这个事务所占的资源(行记录或者表)就会被锁定,所以优化SQL、合理使用SQL是避免数据库锁表和系统崩溃的重要保障。

    看SQL:

    BEGIN;
    
    UPDATE tapp_user
    SET `status` ='active', modified = NOW()
    WHERE
        order_id = (
            SELECT
                id
            FROM
                tapp_user_order
            WHERE
                order_no = 'f28c5e82683d4ccf8c7104d83b949276'
        )
    AND `status` = 'inactive'
    ;
    
    COMMIT;
    

    这个 sql 是根据订单号更新用户的一个状态,但是订单号在订单表,状态在用户表,此时根据订单号查询到对应的用户,再去更新用户状态。

    首先,这条SQL语句是表级锁,也就是意味着整个 tapp_user 表都会被锁定,任何一条更新 tapp_user 表的记录都要等待。

    测试:

    1、我们打开Navicat,新建一个查询,运行 begin;
    2、然后再运行SQL ,注意不 commit;
    3、再新建一个查询,运行begin;
    4、接着在这个新的查询页里面运行一条简单的SQL 比如: update tapp_user set status = 'inactive' where id = 65;
    此时我们就可以看到两个SQL都是一直在执行的状态,没有出现执行结果。直到报错:

    lock.jpg

    有些朋友就会问了,自己经常这么写,为什么没有问题?
    答: 数据量还不够,并发还不够多。
    如果订单表里面有上千万的数据,并发量达到1000+ ,稍微有什么地方没弄好,就会出现系统卡顿,然后宕机。

    日志里一般会有:

    [Err] 1205 - Lock wait timeout exceeded; try restarting transaction
    

    所以我们使用update语句的时候,要尽量避免表级锁,能用主键查询的尽量用主键,比如根据订单更新,就可以先根据订单号查询订单表,再根据订单表找到用户表,这样效率反而会增加。

    相关文章

      网友评论

          本文标题:update 锁表经验分享(2)

          本文链接:https://www.haomeiwen.com/subject/lbneaqtx.html