Kaynağa Gözat

:bug: 索引嵌入块内容可能会导致内核崩溃 https://github.com/siyuan-note/siyuan/issues/7213

Liang Ding 2 yıl önce
ebeveyn
işleme
204580bf36
4 değiştirilmiş dosya ile 29 ekleme ve 14 silme
  1. 2 2
      kernel/model/index.go
  2. 3 7
      kernel/sql/block.go
  3. 2 0
      kernel/sql/block_query.go
  4. 22 5
      kernel/sql/queue.go

+ 2 - 2
kernel/model/index.go

@@ -204,7 +204,7 @@ func autoIndexEmbedBlock(embedBlocks []*sql.Block) {
 		if "" == embedBlock.Content {
 			embedBlock.Content = "no query result"
 		}
-		sql.UpdateBlockContent(embedBlock)
+		sql.UpdateBlockContentQueue(embedBlock)
 
 		if 63 <= i { // 一次任务中最多处理 64 个嵌入块,防止卡顿
 			break
@@ -225,7 +225,7 @@ func updateEmbedBlockContent(embedBlockID string, queryResultBlocks []*EmbedBloc
 	if "" == embedBlock.Content {
 		embedBlock.Content = "no query result"
 	}
-	sql.UpdateBlockContent(embedBlock)
+	sql.UpdateBlockContentQueue(embedBlock)
 }
 
 func init() {

+ 3 - 7
kernel/sql/block.go

@@ -66,12 +66,7 @@ func updateRootContent(tx *sql.Tx, content, updated, id string) (err error) {
 	return
 }
 
-func UpdateBlockContent(block *Block) {
-	tx, err := beginTx()
-	if nil != err {
-		return
-	}
-
+func updateBlockContent(tx *sql.Tx, block *Block) (err error) {
 	stmt := "UPDATE blocks SET content = ? WHERE id = ?"
 	if err = execStmtTx(tx, stmt, block.Content, block.ID); nil != err {
 		tx.Rollback()
@@ -89,6 +84,7 @@ func UpdateBlockContent(block *Block) {
 			return
 		}
 	}
-	tx.Commit()
+
 	putBlockCache(block)
+	return
 }

+ 2 - 0
kernel/sql/block_query.go

@@ -474,6 +474,8 @@ func selectBlocksRawStmt(stmt string, limit int) (ret []*Block) {
 			if confLimit && limit < len(ret) {
 				break
 			}
+		} else {
+			logging.LogWarnf("raw sql query [%s] failed: %s", stmt, err)
 		}
 	}
 	return

+ 22 - 5
kernel/sql/queue.go

@@ -41,7 +41,7 @@ var (
 
 type dbQueueOperation struct {
 	inQueueTime time.Time
-	action      string // upsert/delete/delete_id/rename/delete_box/delete_box_refs/insert_refs/index/delete_ids
+	action      string // upsert/delete/delete_id/rename/delete_box/delete_box_refs/insert_refs/index/delete_ids/update_block_content
 
 	indexPath                     string      // index
 	upsertTree                    *parse.Tree // upsert/insert_refs
@@ -51,6 +51,7 @@ type dbQueueOperation struct {
 	box                           string      // delete_box/delete_box_refs/index
 	renameTree                    *parse.Tree // rename
 	renameTreeOldHPath            string      // rename
+	block                         *Block      // update_block_content
 }
 
 func FlushTxJob() {
@@ -166,6 +167,8 @@ func execOp(op *dbQueueOperation, tx *sql.Tx, context map[string]interface{}) (e
 		err = insertRefs(tx, op.upsertTree)
 	case "update_refs":
 		err = upsertRefs(tx, op.upsertTree)
+	case "update_block_content":
+		err = updateBlockContent(tx, op.block)
 	default:
 		msg := fmt.Sprintf("unknown operation [%s]", op.action)
 		logging.LogErrorf(msg)
@@ -174,13 +177,18 @@ func execOp(op *dbQueueOperation, tx *sql.Tx, context map[string]interface{}) (e
 	return
 }
 
-func mergeUpsertTrees() (ops []*dbQueueOperation) {
+func UpdateBlockContentQueue(block *Block) {
 	dbQueueLock.Lock()
 	defer dbQueueLock.Unlock()
 
-	ops = operationQueue
-	operationQueue = nil
-	return
+	newOp := &dbQueueOperation{block: block, inQueueTime: time.Now(), action: "update_block_content"}
+	for i, op := range operationQueue {
+		if "update_block_content" == op.action && op.block.ID == block.ID {
+			operationQueue[i] = newOp
+			return
+		}
+	}
+	operationQueue = append(operationQueue, newOp)
 }
 
 func UpdateRefsTreeQueue(tree *parse.Tree) {
@@ -320,3 +328,12 @@ func RemoveTreePathQueue(treeBox, treePathPrefix string) {
 	}
 	operationQueue = append(operationQueue, newOp)
 }
+
+func mergeUpsertTrees() (ops []*dbQueueOperation) {
+	dbQueueLock.Lock()
+	defer dbQueueLock.Unlock()
+
+	ops = operationQueue
+	operationQueue = nil
+	return
+}