ApplyLobsterPerformanceSchemaPatch.java 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import java.sql.Connection;
  2. import java.sql.DriverManager;
  3. import java.sql.ResultSet;
  4. import java.sql.Statement;
  5. /**
  6. * Patch schema gaps that cause optional-page / scheduler warnings.
  7. * Usage: java -cp mysql-connector-j.jar;. ApplyLobsterPerformanceSchemaPatch [db1 db2 ...]
  8. */
  9. public class ApplyLobsterPerformanceSchemaPatch {
  10. private static final String HOST = "cq-cdb-8fjmemkb.sql.tencentcdb.com:27220";
  11. private static final String USER = "root";
  12. private static final String PWD = "Ylrz_1q2w3e4r5t6y";
  13. private static final String TOKEN_TABLE = """
  14. CREATE TABLE IF NOT EXISTS `lobster_token_consumption` (
  15. `id` bigint NOT NULL AUTO_INCREMENT,
  16. `company_id` bigint NOT NULL COMMENT '\u516c\u53f8ID',
  17. `instance_id` bigint DEFAULT NULL COMMENT '\u5b9e\u4f8bID',
  18. `node_code` varchar(100) DEFAULT NULL COMMENT '\u8282\u70b9\u7f16\u7801',
  19. `model_identifier` varchar(200) DEFAULT NULL COMMENT '\u6a21\u578b\u6807\u8bc6',
  20. `consume_type` varchar(50) DEFAULT NULL COMMENT '\u6d88\u8017\u7c7b\u578b',
  21. `token_count` bigint DEFAULT 0 COMMENT 'Token\u6570\u91cf',
  22. `estimated_cost` decimal(18,6) DEFAULT NULL COMMENT '\u9884\u4f30\u6210\u672c',
  23. `request_time` datetime DEFAULT NULL COMMENT '\u8bf7\u6c42\u65f6\u95f4',
  24. `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
  25. PRIMARY KEY (`id`),
  26. KEY `idx_company_time` (`company_id`, `request_time`)
  27. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='\u9f99\u8679Token\u6d88\u8017\u8bb0\u5f55'
  28. """;
  29. public static void main(String[] args) throws Exception {
  30. String[] dbs = args.length > 0 ? args : new String[]{"fs_tenant_cs1", "ylrz_saas"};
  31. for (String db : dbs) {
  32. System.out.println("\n===== " + db + " =====");
  33. String url = "jdbc:mysql://" + HOST + "/" + db + "?useSSL=false&serverTimezone=GMT%2B8";
  34. try (Connection c = DriverManager.getConnection(url, USER, PWD);
  35. Statement st = c.createStatement()) {
  36. st.execute(TOKEN_TABLE);
  37. addColumnIfMissing(st, c, "lobster_sales_corpus", "optimized_answer",
  38. pickAfterColumn(c, "lobster_sales_corpus",
  39. new String[]{"quality_status", "status", "sales_answer", "customer_question"},
  40. "optimized_answer text NULL"));
  41. addColumnIfMissing(st, c, "lobster_sales_corpus", "ai_feedback",
  42. pickAfterColumn(c, "lobster_sales_corpus",
  43. new String[]{"optimized_answer", "sales_answer"},
  44. "ai_feedback text NULL"));
  45. addColumnIfMissing(st, c, "company_workflow_lobster_task", "external_contact_id",
  46. "ALTER TABLE company_workflow_lobster_task ADD COLUMN external_contact_id bigint DEFAULT NULL COMMENT 'qw_external_contact.id' AFTER binding_id");
  47. addColumnIfMissing(st, c, "company_workflow_lobster_task", "channel_type",
  48. "ALTER TABLE company_workflow_lobster_task ADD COLUMN channel_type varchar(30) DEFAULT 'QW' COMMENT '\u6e20\u9053\u7c7b\u578b QW/WX/IM' AFTER external_contact_id");
  49. addColumnIfMissing(st, c, "company_workflow_lobster_task", "channel_contact_id",
  50. "ALTER TABLE company_workflow_lobster_task ADD COLUMN channel_contact_id bigint DEFAULT NULL COMMENT '\u6e20\u9053\u8054\u7cfb\u4ebaID' AFTER channel_type");
  51. addColumnIfMissing(st, c, "company_workflow_lobster_task", "channel_context_json",
  52. "ALTER TABLE company_workflow_lobster_task ADD COLUMN channel_context_json text COMMENT '\u6e20\u9053\u4e0a\u4e0b\u6587JSON' AFTER channel_contact_id");
  53. audit(c);
  54. }
  55. }
  56. }
  57. private static String pickAfterColumn(Connection c, String table, String[] candidates, String columnDef)
  58. throws Exception {
  59. for (String col : candidates) {
  60. if (columnExists(c, table, col)) {
  61. return "ALTER TABLE " + table + " ADD COLUMN " + columnDef + " AFTER " + col;
  62. }
  63. }
  64. return "ALTER TABLE " + table + " ADD COLUMN " + columnDef;
  65. }
  66. private static void addColumnIfMissing(Statement st, Connection c, String table, String column, String ddl)
  67. throws Exception {
  68. if (columnExists(c, table, column)) {
  69. System.out.println("[SKIP] " + table + "." + column);
  70. return;
  71. }
  72. st.execute(ddl);
  73. System.out.println("[OK] " + table + "." + column);
  74. }
  75. private static boolean columnExists(Connection c, String table, String column) throws Exception {
  76. try (ResultSet rs = c.getMetaData().getColumns(c.getCatalog(), null, table, column)) {
  77. return rs.next();
  78. }
  79. }
  80. private static void audit(Connection c) throws Exception {
  81. try (Statement st = c.createStatement()) {
  82. printExists(st, "lobster_token_consumption");
  83. printColumn(st, "lobster_sales_corpus", "optimized_answer");
  84. printColumn(st, "company_workflow_lobster_task", "external_contact_id");
  85. }
  86. }
  87. private static void printExists(Statement st, String table) throws Exception {
  88. try (ResultSet rs = st.executeQuery(
  89. "SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='" + table + "'")) {
  90. rs.next();
  91. System.out.println(" " + table + " exists=" + (rs.getInt(1) > 0));
  92. }
  93. }
  94. private static void printColumn(Statement st, String table, String column) throws Exception {
  95. try (ResultSet rs = st.executeQuery(
  96. "SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='"
  97. + table + "' AND COLUMN_NAME='" + column + "'")) {
  98. rs.next();
  99. System.out.println(" " + table + "." + column + " exists=" + (rs.getInt(1) > 0));
  100. }
  101. }
  102. }