排除 go-mssqldb 驅動程式的故障

本文提供常見錯誤及與駕駛者連接 go-mssqldb 問題的解決方案。

從最簡單的檢查開始

在啟用詳細記錄或變更集區設定之前,請先逐項檢查下列清單:

  1. 確認基本可達性:伺服器名稱、埠口、防火牆規則,以及 SQL Server 或 Azure SQL 是否接受連線。
  2. 驗證認證輸入:驅動程式名稱、使用者名稱、密碼、網域格式或 fedauth 設定。
  3. 確認 TLS 設定: encrypt、憑證路徑、 hostnameincertificate以及是否 TrustServerCertificate 適合該環境。
  4. 只有在確認連線設定正確後,才應著手排查連線池耗盡、失效連線、重試邏輯,以及緩慢或遭阻塞查詢的診斷問題。

若發生連線設定失敗,請參閱本文前面的章節。 只有在連線至少有時能成功,且之後會在高負載、閒置一段時間後或容錯移轉期間失敗時,才使用後續章節。

連線錯誤

以下章節將介紹常見的連線相關錯誤訊息及其解決方案。

無法開啟 TCP 連線

錯誤訊息: unable to open tcp connection with host 'localhost:1433': dial tcp 127.0.0.1:1433: connectex: No connection could be made because the target machine actively refused it.

原因和解決方案

  • SQL Server 沒有在執行。 啟動 SQL Server 服務。
  • TCP/IP 沒有啟用。 開啟 SQL Server 組態管理員,並在 SQL Server 網路設定>協定中啟用 TCP/IP。
  • 換錯端口了。 請在 SQL Server 組態管理員中確認連接埠,或針對具名執行個體使用 SQL Server Browser。
  • 防火牆阻擋了該埠。 為埠 1433(或你設定的埠)新增一個入站規則。

使用者的登入失敗

錯誤訊息: mssql: login error: Login failed for user '<user>'.

原因和解決方案

  • 使用者名稱或密碼錯誤。 請核實憑證。
  • SQL Server 認證已被停用。 在伺服器屬性中啟用 SQL Server 和 Windows 認證模式
  • 登入帳號根本不存在。 在 SQL Server 建立登入。
  • 登入帳號無法存取目標資料庫。 使用 CREATE USER 授與資料庫存取權限。

憑證驗證錯誤

錯誤訊息: TLS Handshake failed: x509: certificate signed by unknown authority

原因和解決方案

  • 伺服器使用自簽憑證。 提供帶有 certificate or serverCertificate 參數的憑證路徑,或僅設定 TrustServerCertificate=true 為開發。
  • CA 憑證不在系統信任儲存庫裡。 將 CA 憑證加入作業系統信任儲存庫,或以 certificate 參數指定。
  • 主機名稱不符。 請使用 hostnameincertificate 來指定憑證中預期的名稱。

欲了解更多資訊,請參閱 加密與憑證

連線已逾時

錯誤訊息: unable to open tcp connection with host '<server>:1433': dial tcp: i/o timeout

原因和解決方案

  • 網路連線問題。 請透過使用 telnet <server> 1433Test-NetConnection -ComputerName <server> -Port 1433確認你能連上伺服器。
  • DNS 解析失敗。 確認主機名稱是否正確解析。
  • 增加dial timeoutconnection timeout在 連接字串 中。

認證錯誤

以下章節涵蓋認證錯誤訊息。

NTLM 認證失敗

錯誤訊息: NTLM authentication failed

原因和解決方案

  • 網域格式錯誤。 在參數DOMAIN\user中使用user id。 在 URL 格式中,將反斜線編碼為 %5C
  • 密碼錯了。 驗證網域密碼。

Kerberos 認證失敗

錯誤訊息: krb5: cannot resolve KDC for realm

原因和解決方案

  • 缺少或設定 /etc/krb5.conf錯誤。 請確認該 [realms] 區塊包含你網域正確的 KDC 地址。
  • 沒有有效票。 跑 klist 去檢查有效票券,或跑 kinit 去拿一張。
  • 找不到 Keytab 檔案。 在參數 krb5-keytabfile 中驗證路徑。

欲了解更多資訊,請參閱 SQL Server 與 Windows 驗證

Microsoft Entra ID 認證失敗

錯誤訊息clientCredentialFromCert: error reading certificate: ...DefaultAzureCredential: failed to acquire a token

原因和解決方案

  • 客戶 ID、租戶 ID 或客戶秘密錯誤。 確認 連接字串 或環境變數的值。
  • 主機上的管理身份並沒有被設定。 請在 Azure 入口網站驗證身份。
  • 缺少 azuread 套件匯入。 匯入 github.com/microsoft/go-mssqldb/azuread 並使用 azuresql 驅動程式名稱。

欲了解更多資訊,請參閱 Microsoft Entra ID 認證

使用者登入失敗 ''(空使用者名稱)

錯誤訊息: mssql: login error: Login failed for user ''.

原因:你使用了搭配 fedauth 參數的 sql.Open("sqlserver", ...)。 Entra ID 驗證需要由 azuread 套件註冊的 azuresql 驅動程式名稱。 使用標準 sqlserver 驅動程式時, fedauth 參數會被忽略,驅動程式嘗試在沒有使用者名稱的情況下進行 SQL 認證。

解決方案:匯入 azuread 套件並使用 azuresql 驅動程式名稱:

import _ "github.com/microsoft/go-mssqldb/azuread"

db, err := sql.Open("azuresql",
    "sqlserver://<server>.database.windows.net?database=AdventureWorks2025&fedauth=ActiveDirectoryDefault&encrypt=true&TrustServerCertificate=false")
if err != nil {
    panic(err)
}

欲了解更多資訊,請參閱 Microsoft Entra ID 認證

查詢錯誤

以下章節涵蓋查詢執行錯誤訊息。

不支援 LastInsertID

錯誤訊息: LastInsertId is not supported. Please use the OUTPUT clause or add 'select ID = convert(bigint, SCOPE_IDENTITY())' to the end of your query.

解決方法go-mssqldb 驅動程式不支援 LastInsertId()。 請分別使用 OUTPUT 子句或查詢 SCOPE_IDENTITY()

暫存資料表未找到

錯誤訊息: mssql: Invalid object name '#TempTable'.

原因:暫存資料表是針對每個連線設置的。 如果你在一次呼叫中建立臨時資料表,並在另一次呼叫中查詢該資料表,這兩次呼叫可能會從連線池取得不同的連線。

解決方案:使用 db.Conn(ctx) 釘選至單一連線,或將作業包在交易中。

欲了解更多資訊,請參閱 儲存程序

Azure SQL 錯誤

以下章節將介紹 Azure SQL Database 特有的錯誤。

瞬態連線錯誤編號

請使用以下共享清單作為暫時性連線建立錯誤及請求路徑傳輸失敗的參考,這些錯誤符合有界重試的資格:

以下錯誤發生在連線建立或向伺服器發送請求時,屬於暫時性。 以短暫且有上限的退避間隔進行重試。 重複幾次後仍持續的錯誤通常表示設定有問題(伺服器錯誤、權限遺失、配額用盡),重試無法解決。

錯誤 Message Troubleshooting
64 A connection was successfully established with the server, but then an error occurred during the login process. (provider: TCP Provider, error: 0 - The specified network name is no longer available.) TCP 連線在握手中途中斷。 不是憑證故障。 如果問題持續,請檢查是否有用戶端網路不穩定或中介裝置中斷半建立連線。
233 The client was unable to establish a connection because of an error during connection initialization process before login. 登入前傳輸或 TLS 失敗。 伺服器通常會在無法接受連線時回傳(資源耗盡、連線數達最大或客戶端不支援)。 不是憑證故障。 確認伺服器健康狀況,然後檢查客戶端登入逾時、TLS 設定,以及客戶端/伺服器 TLS 版本相容性。
4060 Cannot open database "%.*ls" requested by the login. The login failed. 登入功能會驗證,但無法開啟指定的資料庫。 暫時性原因包括資料庫處於過渡狀態(故障轉移、還原、縮放)或自動暫停。 持續性原因(資料庫不存在、登入無法存取)不會透過重試解決;檢查資料庫名稱、登入映射和資料庫狀態。
4221 Login to read-secondary failed due to long wait on 'HADR_DATABASE_WAIT_FOR_TRANSITION_TO_VERSIONING'. 此副本無法供登入使用,因為在副本被回收時仍在進行中的交易缺少資料列版本。 回滾或提交主要節點上作用中的交易,以解決此問題。 透過避免在主節點上進行長時間的寫入交易來緩解。
10053 A transport-level error has occurred when sending the request to the server. (provider: TCP Provider, error: 0 - An established connection was aborted by the software in your host machine.) 當地方面終止了連結。 檢查用戶端網路健康狀況以及任何本地防火牆或 VPN 用戶端。
10054 A transport-level error has occurred when sending the request to the server. (provider: TCP Provider, error: 0 - An existing connection was forcibly closed by the remote host.) 遠端會發送 TCP 重置。 常見原因包括:對等程序當機、防火牆注入重置,或 Azure SQL 閘道關閉閒置連線。 對於閒置後重置的情況,請在用戶端啟用 TCP keepalive,或縮短連線集區的閒置逾時時間。
10928 Resource ID: %d. The %s limit for the database is %d and has been reached. See 'http://go.microsoft.com/fwlink/?LinkId=267637' for assistance. 資料庫超過 Azure SQL 資源治理限制。 資源 ID 1 表示工作者上限;資源 ID 2 表示工作階段上限。 從訊息中識別限制型態,然後減少並行性、擴充資料庫規模,或縮短長期執行的資源操作。
10929 Resource ID: %d. The %s minimum guarantee is %d, maximum limit is %d, and the current usage for the database is %d. However, the server is currently too busy to support requests greater than %d for this database. 資料庫已超出其最低保證門檻,且底層伺服器正在節流。 當鄰居負載下降時,重試通常會成功。 持續發生的情況表示你需要更高的服務層級或較少噪音的環境。
40020401434016640540 在容錯移轉期間,於錯誤 40197 的 Error code %d 欄位中回報。 子碼嵌入 40197 故障轉移訊息中,部分路徑會以頂層錯誤編號浮現。 把他們當成40197一樣對待。
40197 The service has encountered an error processing your request. Please try again. Error code %d. 軟體升級、硬體故障或其他 Azure SQL 故障轉移事件。 重新連接會引導你到健康的複製品。 嵌入的錯誤代碼用來識別故障轉移類型。 如果錯誤持續,請擷取會話追蹤 ID,並聯絡客服。
40501 The service is currently busy. Retry the request after 10 seconds. Incident ID: %ls. Code: %d. Azure SQL 引擎節流 建議的底線是10秒後退。 持續節流表示工作負載已超出資料庫獲配的資源;請提高服務層級或減少並行作業數。
40613 Database '%.*ls' on server '%.*ls' is not currently available. Please retry the connection later. If the problem persists, contact customer support, and provide them with the session tracing ID of '%.*ls'. 資料庫無法使用,通常發生在故障轉移期間,或在調整規模作業期間短暫發生。 在後退時重試;如果問題持續超過幾分鐘,擷取會話追蹤 ID,並開啟支援案件。
42108 Can not connect to the SQL pool since it is paused. Please resume the SQL pool and try again. 專用的 SQL 池(Synapse)處於暫停狀態。 只有在池子恢復後,重試才會成功。 可以明確恢復集區,或將工作負載排程為在集區恢復後執行。
42109 The SQL pool is warming up. Please try again. 專用的 SQL 池正在恢復運作。 在後退區重試直到池子上線;暖身通常需要幾分鐘。
49918 Cannot process request. Not enough resources to process request. The service is currently busy. Please retry the request later. 伺服器目前無法分配足夠的資源來滿足這個請求。 在後退時重試。 如果錯誤持續,就擴大資料庫或彈性池。
49919 Cannot process create or update request. Too many create or update operations in progress for subscription "%ld". 管理操作的訂閱層級並行限制。 減少並行的建立/更新呼叫,或將其錯開執行。
49920 Cannot process request. Too many operations in progress for subscription "%ld". 飛行中操作的訂閱級並行限制。 降低並行度,或等待進行中的作業完成。

語句層級錯誤不在此列表中,因為它們會在連線建立後觸發,且失敗後會讓會話仍可用。 最常見的可重試語句錯誤是 1205(死鎖受害者)和 1222(鎖-請求逾時)。 請重試整個交易作業,而不是只重試失敗的單一陳述式。

錯誤訊息內容來自 Azure SQL 暫時性連線錯誤。 個別驅動程式會維護各自的內建重試清單;此目錄說明在 SQL Server、Azure SQL Database、Azure SQL 受控執行個體、Microsoft Fabric 中的 SQL 資料庫,以及 Azure Synapse Analytics 中的專用 SQL 集區中,哪些錯誤符合重試資格

無法開啟伺服器(防火牆)

錯誤訊息: mssql: login error: Cannot open server '<server>' requested by the login. Client with IP address '203.0.113.42' is not allowed to access the server.

原因和解決方案

  • 你的客戶端 IP 不在 Azure SQL 防火牆規則中。 在 Azure 入口網站新增防火牆規則:SQL server>Networking>新增防火牆規則
  • 如果你的應用程式在 Azure 上執行,請啟用允許 Azure 服務與資源存取此伺服器
  • 若要私有連線,請設定私有端點。

資源限制已達上限

錯誤訊息: mssql: Resource ID: 1. The session limit for the database is 300 and has been reached.

原因和解決方案

  • Azure SQL 層級的同時連線太多了。 在你的集區組態中調低 MaxOpenConns
  • 連線洩漏(未封閉的列或交易)。 檢查是否遺漏了對 defer rows.Close()defer tx.Rollback() 的呼叫。
  • 多個應用程式共用資料庫。 將連線限制平均分配到所有用戶端。

關於按層分類的 Azure SQL 連線限制,請參閱 Azure SQL Database

服務目前繁忙(限流中)

錯誤訊息: mssql: The service is currently busy. Retry the request after 10 seconds. Code: 40501.

原因和解決方案

  • 資料庫負載沉重。 實作帶有指數退縮的重試邏輯。
  • 工作負載超過該層級的 DTU 或 vCore 容量。 考慮擴大規模。

關於重試實作模式,請參見 錯誤處理與重試模式

資料庫目前無法取得

錯誤訊息: mssql: Database 'AdventureWorks2025' on server '<server>' is not currently available. Code: 40613.

原因:Azure SQL 正在重新設定資料庫(故障轉移、更新或擴展操作)。 此狀態為暫態錯誤。

解決方法:重試手術。 資料庫通常在幾秒內即可開放。 欲了解更多資訊,請參閱 錯誤處理與重試模式

連線錯誤

錯誤 driver: bad connection 表示駕駛偵測到現有連線已無法使用。 database/sql 集區會自動在新的連線上重試非交易式呼叫的操作,但在作用中的交易內執行的操作會立即失敗。

如果應用程式從未成功連接,請不要從這部分開始。 driver: bad connection 通常表示連線重用、故障轉移、閒置逾時,或是在初始連線已建立且正常運作後發生的網路中斷。

常見原因

原因 一般案例 修復
Azure SQL 閘道閒置逾時 連線在 Azure 閘道後方閒置了 30+ 分鐘。 設定 db.SetConnMaxIdleTime(2 * time.Minute),使其在閘道器中斷閒置連線之前先回收這些連線。
網路中斷 用戶端與伺服器間的暫時性網路故障。 為非交易操作實作重試邏輯。 請參見 錯誤處理
伺服器端會話終止 DBA 終止了會話,或是伺服器被重新啟動。 重試。 將 db.SetConnMaxLifetime 設為輪替連線。
Azure SQL 重新設定 故障轉移、擴充或修補作業導致連線中斷。 ConnMaxLifetime 設為 5 分鐘或更短。 實作重試邏輯:
長期交易逾時 Azure SQL 終止了 session (error 40549). 保持交易簡潔。 將大型作業拆分成較小的批次。

資料庫/SQL 如何處理不良連線

對於交易之外的呼叫(db.QueryContextdb.ExecContext),當驅動程式回報連線異常時,database/sql 集區會自動在新的連線上重試該操作。 這個重試對你的程式碼是透明的。

對於交易內的呼叫(tx.QueryContexttx.ExecContext),連線集區無法重試,因為交易狀態會遺失。 你的程式碼必須捕捉錯誤、回滾,並重新嘗試整個交易作業。

設定集區以處理 Azure 閘道逾時和容錯移轉:

db.SetConnMaxLifetime(5 * time.Minute)  // Rotate connections to recover from failovers.
db.SetConnMaxIdleTime(2 * time.Minute)  // Recycle before Azure gateway drops idle connections (30 min).
db.SetMaxIdleConns(10)                  // Keep warm connections for quick recovery.
db.SetMaxOpenConns(20)                  // Stay below your tier's connection limit.

對於內部部署 SQL Server,ConnMaxIdleTime 較不那麼重要,因為沒有閘道閒置逾時限制。 不過,設定它可以防止網路中斷後連線過時的情況。

如需詳細設定指引,請參閱 Azure SQL Database

泳池耗盡

連線池耗盡是指連線池中的所有連線都在使用中,而新的呼叫端會遭到阻塞並等待可用連線。

Symptoms

  • 請求在高負載下會變慢或逾時。
  • db.Stats().WaitCount 持續成長。
  • db.Stats().InUse 等於 MaxOpenConns.
  • 情境截止時間超過尖峰時的錯誤。

診斷

在您的應用程式中加入泳池監控:

stats := db.Stats()
log.Printf("Pool: open=%d inUse=%d idle=%d waitCount=%d waitDuration=%v",
    stats.OpenConnections, stats.InUse, stats.Idle,
    stats.WaitCount, stats.WaitDuration)

常見原因和解決方案

原因 如何識別 修復
rows.Close() 未被呼叫 InUse 隨時間增長,從未減少。 在每個 QueryContext 後面加上 defer rows.Close()
長時間執行的交易 InUse 在批次處理期間會保持高溫。 保持交易簡潔。 將大批次分成較小批次處理。
MaxOpenConns 太低了 WaitCount 排除固定資源和漏水後,正常負載下會穩定生長。 增加 MaxOpenConns
MaxOpenConns 未設定 尖峰負載下有數百個開啟的連線。 設定 MaxOpenConns 為有界值。
呼叫 db.Conn 時發生 Goroutine 洩漏 InUse 成長,但請求量卻沒有相應成長。 確保每個 db.Conn() 結果都以 defer conn.Close()閉合。

如需詳細的連線集區組態指引,請參閱 連線集區

查詢診斷緩慢或阻塞

設定查詢逾時時間

利用 context 截止時間找出慢查詢,並防止遭阻塞的 SQL 呼叫占住連線,導致呼叫端停滯:

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

rows, err := db.QueryContext(ctx, "SELECT * FROM LargeTable WHERE Status = @s",
    sql.Named("s", "active"))
if err != nil {
    // Check if the error was a timeout.
    if ctx.Err() == context.DeadlineExceeded {
        log.Println("Query exceeded 5-second timeout")
    }
    return err
}
defer rows.Close()

完整的效能調查工作流程,包括 查詢存放區、DMV、缺失索引分析及基準測試,請參見效能調整

死結診斷

錯誤訊息: mssql: Transaction (Process ID 52) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

錯誤號碼:1205

解決方案:死結發生在並行系統中。 為錯誤 1205 實作自動重試邏輯。 關於死鎖重試包裝函式,請參見 交易

預防策略

  • 所有查詢都能以相同順序存取資料表。
  • 保持交易簡短,避免交易過程中的使用者互動。
  • 使用 READ COMMITTED SNAPSHOT 隔離來減少鎖的爭用。

同一查詢重複死關表示設計有問題。 使用死鎖圖(透過擴展事件或系統健康會話擷取)來識別競爭的語句與鎖類型。 完整攻略請參考 Deadlocks 指南。 關於 Go 中的死結處理策略,請參見死鎖處理處理死鎖。

容器憑證錯誤(Go 1.23 及更新版本)

錯誤訊息: x509: negative serial number

原因:Go 1.23 嚴格執行 RFC 5280。 SQL Server 在 Docker 容器中產生的自簽憑證使用負序號,Go 會拒絕此序號。

解決方案:

  • 對於測試環境,可以新增 TrustServerCertificate=true 跳過憑證驗證,或 encrypt=disable 完全關閉加密功能。
  • 對於 CI/CD,設定GODEBUG=x509negativeserial=1環境變數恢復 Go 1.23 之前的行為,且不更改你的 連接字串。
  • go.mod (Go 1.23 及後續版本) 中,加入 godebug x509negativeserial=1 指示詞,以便在建置時套用覆寫。

警告

不要使用 TrustServerCertificate=trueencrypt=disable 在生產環境中使用。 這些選項會關閉安全檢查。 生產時,請使用正式簽署的憑證。

SHA-1 憑證錯誤(Go 1.24 及更新版本)

錯誤訊息tls: handshake failureTLS Handshake failed: EOF在連接較舊的 SQL Server 實例時出現。

原因:Go 1.24 預設不允許 TLS 憑證中使用 SHA-1 簽章演算法。 較舊的 SQL Server 版本及部分本地安裝使用以 SHA-1 簽署的憑證。

解決方案:

  • 建議重新核發 SHA-256 或更新版本的伺服器憑證。
  • 設定 GODEBUG=tlssha1=1 環境變數暫時重新啟用 SHA-1 支援。
  • go.mod (Go 1.23 及更新版本)中,新增指令 godebug tlssha1=1

何時使用 encrypt=disableTrustServerCertificate=true

Setting 其功能是什麼 何時使用
TrustServerCertificate=true 它會加密流量,但跳過憑證驗證。 本地開發與測試,伺服器使用自簽憑證。
encrypt=disable 以明文傳送流量(無 TLS)。 無法使用 TLS 的舊環境。 不推薦。
encrypt=strict TDS 8.0,從第一個位元組開始就具備完整的 TLS 驗證。 Production on SQL Server 2022 或 Azure SQL.

欲了解更多資訊,請參閱 測試加密及憑證

編碼與排序問題

隱含轉換警告

如果您將 string 參數(以 nvarchar 的形式傳送)傳遞至 varchar 資料行,SQL Server 會執行隱含轉換,可能導致無法使用索引。

此範例延續本文前面的程式碼片段中的 database/sqlmssql 設定。

解決方案:將mssql.VarChar用於varchar欄位:

db.QueryContext(ctx, "SELECT * FROM Production.Product WHERE ProductNumber = @p1",
    mssql.VarChar("FR-R92B-58"))

CharsetToUTF8 處理非拉丁字元時發生錯誤

錯誤訊息:在查詢 CharsetToUTF8: ... 儲存在類似 SQL_Latin1_General_CP1_CI_AS 的定序中且包含中文、日文或其他非拉丁字元的 varchar 欄位時。

原因:驅動程式嘗試將欄位的代碼頁轉換為 UTF-8,但儲存的位元組與整合預期的編碼不符。

解決方案:

  • 對於儲存非拉丁字元文字的資料行,請使用 nvarchar 而非 varcharnvarchar 以 UTF-16 格式儲存資料,避免代碼頁轉換。
  • 如果你無法更改欄位類型,請確認資料庫整合是否支援你儲存的字元集。

啟用診斷日誌

使用 log 連線參數來啟用驅動程式層級的日誌記錄:

sqlserver://<user>:<password>@<server>?database=AdventureWorks2025&log=63

日誌標誌是位元遮罩值: 1 (錯誤)、 2 (訊息)、 4 (列)、 8 (SQL)、 16 (參數)、 32 (交易)、 64 (除錯)。 將值加起來(例如, 63 = 除除錯外的全部, 127 = 全部)。

程式化日誌記錄時,請使用 SetLoggerSetContextLogger。 請參見 日誌與診斷

故障排除清單

癥狀 第一步
連線被拒 確認 SQL Server 是否在執行且 TCP/IP 是否啟用。
登入失敗 檢查憑證和認證模式。
憑證錯誤 檢查伺服器憑證,或設定 TrustServerCertificate=true(僅限開發用途)。
連線超時 使用 Test-NetConnection 驗證網路路徑。 檢查防火牆規則。
Azure SQL 防火牆 將你的 IP 加入 Azure SQL 防火牆規則。
流量限制錯誤 實作具指數退避的重試機制。 升級階級。
連線不良 針對 Azure SQL,將 ConnMaxIdleTime 設定為低於 30 分鐘。 實作重試邏輯:
泳池耗盡 顯示器 db.Stats()。 修正未成交的列/交易。 增加 MaxOpenConns
緩慢查詢 設定情境逾時。 查詢動態管理檢視(DMV)以找出高成本查詢。
死結 在錯誤 1205 上實作重試。 以一致的順序存取資料表。
隱含轉換 mssql.VarChar 用於 varchar 欄位。