Skip to content

Instantly share code, notes, and snippets.

@umonaca
Last active March 21, 2021 04:14
Show Gist options
  • Save umonaca/fef1ebe3c2048b822cf678428774cae1 to your computer and use it in GitHub Desktop.
Save umonaca/fef1ebe3c2048b822cf678428774cae1 to your computer and use it in GitHub Desktop.

锁表原因?

我想了一下最可能造成此次锁表的原因。你是程序在线的时候执行的knex-migrate up吗?那样这次是有可能锁死。 如果你cherry-pick了 935681b14f4f41a6af27977d5cc1cae6c2f5817a 这个是为了解决之前打错字的情况,也为了这次你执行knex-migrate up能正确运行而不至于直接挂在前面的错误文件上。

当你执行knex-migrate的时候,它会读取knex_migrations表,对比没有执行过的migration文件,然后执行并把完成的migration记录文件名到这个表里面。

也就是说本次你应该是看到执行了两个migration:
20210223200240_drop_not_null_constraints.js
20210304101412_fix_view_userMetatdata.js

然后前者20210223200240_drop_not_null_constraints.js是个什么东西呢,为了DROP t_work表里面大量多余的NOT NULL constraints,这个是上游写的bug。 然而SQLite非常麻烦的地方在于它不支持绝大多数ALTER TABLE,导致无论用什么ORM或者Query Builder最后都是得自己手写大段重建整个表的语句,具体你可以看那个文件里做了什么。 这个非常繁琐的步骤也是符合SQLite文档的:https://sqlite.org/lang_altertable.html

然而如果重建过程中或者以后导致数据库锁死,那就只有重启了。

不过现在应该不需要做什么,数据库应该是正常的。

数据库迁移的补充解释

关于Kikoeru内部的数据库迁移逻辑,请看这篇文档
如果你看到knex_migrations表里面有两个只差一个字母的文件:

20210223200240_drop_not_null_constrains.js
20210223200240_drop_not_null_constraints.js

并不会造成问题,但是不放心你可以删掉20210223200240_drop_not_null_constrains.js这个记录。具体原因不解释了,其实是你fork unstable上线的时候我还有没测试完的草稿……

关于你提的VIEW问题

VIEW本身不存储数据,它是完全等价于subquery的。 执行

EXPLAIN QUERY PLAN SELECT * FROM userMetadata
	WHERE user_name = 'admin'
	ORDER BY userRating DESC, "release" DESC, id DESC;

EXPLAIN QUERY PLAN SELECT * FROM (SELECT t_work.id,
      t_work.title,
      json_object('id', t_work.circle_id, 'name', t_circle.name) AS circleObj,
      t_work.release,
      t_work.review_count,
      t_work.dl_count,
      t_work.nsfw,
      userrate.userRating,
      userrate.review_text,
      userrate.progress,
      userrate.updated_at,
      json_object('vas', json_group_array(json_object('id', t_va.id, 'name', t_va.name))) AS vaObj,
      userrate.user_name
    FROM t_work
    JOIN t_circle on t_circle.id = t_work.circle_id
    JOIN r_va_work on r_va_work.work_id = t_work.id
    join t_va on t_va.id = r_va_work.va_id
    JOIN (
        SELECT t_review.work_id,
          t_review.rating AS userRating,
          t_review.review_text,
          t_review.progress,
          strftime('%Y-%m-%d %H-%M-%S', t_review.updated_at, 'localtime') AS updated_at,
          t_review.user_name
        FROM t_review
          JOIN t_work on t_work.id = t_review.work_id
        ) AS userrate
    ON userrate.work_id = t_work.id
    GROUP BY t_work.id, userrate.user_name
    ) AS subquery
    WHERE user_name = 'admin'
    ORDER BY userRating DESC, "release" DESC, id DESC;

可以看到QUERY PLAN是完全一致的。
QUERY PLAN 1
QUERY PLAN 2

@umonaca
Copy link
Author

umonaca commented Mar 18, 2021

我想最需要的大概是按照REST规范重构API。现在像之前写的offload还是补丁套补丁再套补丁。还有很多别的问题:

  • 封面/api/cover应该返回的不是封面本身而是封面地址。
  • 之前提到的无法利用的注入漏洞
  • 路由匹配也非常随意

等过两天打算写一个API草稿。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment