mysql中使用int类型来查询string字段,会进行隐式转换。
如果 该字段存在索引,则会无法使用到 该string类型的索引导致操作超时缓慢。
且如果该字段存在索引则会导致delete操作会进行锁表。其他客户端也无法使用delete操作。导致卡死。
解决问题
此时需要 查看当前有哪些卡住的进程1
SHOW FULL PROCESSLIST ;
然后kill当前进程1
kill 574611;
1.MySQL 隐式转换问题,隐藏的深,不容易被发现,在进行 delete , update 等操作时,一不小心很容易大问题,从而造成事故。
2.对于 delete , update 等操作时,建议先使用 select 语句,看看获取的结果和预期的是否一致,再进行操作,相对会更安全一些。
如果是清空表数据建议直接用 truncate,效率上 truncate 远高于 delete,
应为 truncate 不走事务,不会锁表,也不会生产大量日志写入日志文件;
truncate table table_name 后立刻释放磁盘空间,并重置 auto_increment 的值。
delete 删除不释放磁盘空间,但后续 insert 会覆盖在之前删除的数据上
1.降低写错 SQL 的代价,就算删错了,比如 limit 500, 那也就丢了 500 条数据,并不致命,通过 binlog 也可以很快恢复数据。
2。避免了长事务,delete 执行时 MySQL 会将所有涉及的行加写锁和 Gap 锁(间隙锁),所有 DML 语句执行相关行会被锁住,如果删除数量大,会直接影响相关业务无法使用。
3.delete 数据量大时,不加 limit 容易把 cpu 打满,导致越删越慢。
注: 针对上述第二点,前提是 sex 上加了索引,大家都知道,加锁都是基于索引的,如果 sex 字段没索引,就会扫描到主键索引上,那么就算 sex = 1 的只有一条记录,也会锁表。
对于 delete limit 的使用,MySQL 大佬丁奇有一道题:
如果你要删除一个表里面的前 10000 行数据,有以下三种方法可以做到:
第一种,直接执行 delete from T limit 10000;
第二种,在一个连接中循环执行 20 次 delete from T limit 500;
第三种,在 20 个连接中同时执行 delete from T limit 500。
方案一、事务相对较长,则占用锁的时间较长,会导致其他客户端等待资源时间较长。
方案二、串行化执行,将相对长的事务分成多次相对短的事务,则每次事务占用锁的时间相对较短,其他客户端在等待相应资源的时间也较短。这样的操作,同时也意味着将资源分片使用(每次执行使用不同片段的资源),可以提高并发性。
方案三、人为自己制造锁竞争,加剧并发量。
注: 方案二相对比较好,具体还要结合实际业务场景。
参考: https://blog.csdn.net/weixin_39939530/article/details/110506783