专栏首页若是烟花记一次关于MySQL与PHP的蠢事

记一次关于MySQL与PHP的蠢事

事情是这样的

缘由:

一个稍微有些小复杂的事务。首先需要初始化一些记录的值,然后选取一些新的记录,对新的记录进行排序,然后再将排序等信息写入。

出现的问题:

SQL是按照 id in (xxx, xxx) 来写的。

# 这就是问题所在, 按这个查找 会出现一些意料不到的问题。
SELECT * FROM infos WHERE id IN(55001170412000002)

数据库id 存储是使用的 varchar(50), id形如 55001170412000002, 已经超过了默认的int11。

之前的失误

由于内部系统,使用的CI没有考虑注入之类的安全问题。 直接使用客户端传递的字段 拼接SQL。前端使用Ajax传递的数字型列表。后台处理方式是简单的增加了 ''。

这个其实是没问题的。问题是 在SQL中,使用了未添加 '' 的列表。

/* $ids_ 为处理过的字符串型列表、$ids 为原始数字型的列表 */
SELECT * FROM '.self::$infos.' WHERE id IN('.$ids.') ORDER BY FIELD(id, '.$ids_.');

第一次错误的处理

在前端 将数字型列表 修改为 字符串型列表。

然后发现后端有处理过的$ids_,然后把SQL修改 全部使用处理过的。

并将前端的修改force push,回滚到未修改的版本。第一次失误:(此处JS存在缓存问题...但当时还没有发现)。

修改之后发现更严重的问题。前端修改排序之后,提交一直等待,然后

Query error: Lock wait timeout exceeded; try restarting transaction

数据库死锁....

第二次修改

第二次失误:使用Postman模拟数据提交,但是却没有再次确认浏览器提交的数据格式。

这也导致了,使用Postman偶尔可以正常提交,多数也是死锁的情况。

第三次修改

第三次失误:粗心的忽略了后台数据库SQL本身报错。也就是 给列表字段加了两次 '''' 单引号。

Query error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'xxxx'

第四个失误:而不是第四次。发现 跟着CI官网的 数据库事务。并没有 try...catch...

这时应该真相就出来了。

开启事务-->执行出错-->异常退出 (并没有回滚或者提交导致)

总结

数据库事务 一定要回滚或者提交

try {
	trans()
	commit()
} catch(Exception e) {
	rollback()
} finally {
	close()?
}

MySQL 死锁相关

mysql> SELECT * FROM information_schema.INNODB_TRX\G
*************************** 1. row ***************************
                    trx_id: 8483802
                 trx_state: RUNNING
               trx_started: 2017-04-24 20:53:54
     trx_requested_lock_id: NULL
          trx_wait_started: NULL
                trx_weight: 12
       trx_mysql_thread_id: 111844
                 trx_query: NULL
       trx_operation_state: NULL
         trx_tables_in_use: 0
         trx_tables_locked: 0
          trx_lock_structs: 5
     trx_lock_memory_bytes: 1248
           trx_rows_locked: 15
         trx_rows_modified: 7
   trx_concurrency_tickets: 0
       trx_isolation_level: REPEATABLE READ
         trx_unique_checks: 1
    trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
 trx_adaptive_hash_latched: 0
 trx_adaptive_hash_timeout: 10000
          trx_is_read_only: 0
trx_autocommit_non_locking: 0
1 row in set (0.04 sec)

# 确认无效后,直接kill掉即可
mysql> kill 111844;
Query OK, 0 rows affected (0.04 sec)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • JavaScript 框架学习(JQuery)

    参考: http://www.w3cschool.cc/jquery/jquery-tutorial.html

    lpe234
  • Tomcat CPU占用100%异常分析与处理

    公司使用阿里云ECS,其实我就是打杂的啦~ 写写代码、部署下服务、申请个语音验证码服务啥的.......

    lpe234
  • 掘金15W沸点简单分析(一)

    爬虫通常是:①得到目标网页URL;②发起HTTP请求得到网页数据;③使用各种方式解析网页得到想要的数据;

    lpe234
  • MySQL 事务没有提交导致 锁等待 Lock wait timeout exceeded

    Lock wait timeout exceeded 当一个SQL执行完了,但未COMMIT,后面的SQL想要执行就是被锁,超时结束; select *...

    汤高
  • A little fun with InnoDB multi-versioning(14.有关InnoDB多版本中的一个小问题)

    执行以下命令,在MySQL CLI中,在一个新的连接上执行,不需要做特别的准备(并且要特别注意执行时间):

    冬天里的懒猫
  • MySQL SQL更新锁定

    版权声明:本文为博主原创文章,欢迎扩散,扩散请务必注明出处。

    Leshami
  • mysql常见错误之Waiting for table metadata lock的解决方法

    海涛
  • Duplicate Key引发的死锁

    在事务1执行INSERT INTO user VALUES(null, 'tenmao', 3);失败后,执行事务2,事务2等待后,再继续执行事务1,触发死锁。

    十毛
  • MySQL FAQ 系列 :如何查看当前最新事务 ID

    个别时候可能需要查看当前最新的事务 ID,以便做一些业务逻辑上的判断(例如利用事务 ID 变化以及前后时差,统计每次事务的响应时长等用途)。本文将介绍两种方法可...

    叶金荣
  • Python+OpenCV调用摄像头接口打造家庭安防系统

    问题描述:使用Python+opencv调用笔记本摄像头接口,定期捕捉图像或录制视频并保存为图像文件或视频文件。可以在家里没有人的时候使用该程序监视家中是否有小...

    Python小屋屋主

扫码关注云+社区

领取腾讯云代金券