SQLServer 2012 登陆异常问题

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介: ## 背景 RDS FOR SQLServer 2012 已经上线一段时间了,从反馈来看大家遇到了很多权限相关的问题,所以建议把[RDS FOR SQLServer 2012权限提升](https://yq.aliyun.com/articles/71919?spm=5176.100240.searchblog.8.LWPvRT)这篇文章作为基础知识先能够理解;再之后针对大家经常遇到的CASE我

背景

RDS FOR SQLServer 2012 已经上线一段时间了,从反馈来看大家遇到了很多权限相关的问题,所以建议把RDS FOR SQLServer 2012权限提升这篇文章作为基础知识先能够理解;再之后针对大家经常遇到的CASE我们会把解决方法分享出来,本篇文章是其中之一。

问题

用户应用链接数据库失败 持续报错,业务因此停滞,使用SSMS链接也出错

1.png

Detail

    
    ===================================
    
    Cannot connect to ***
    
    ===================================
    
    Cannot open user default database. Login failed.
    Login failed for user 'option_u'. (.Net SqlClient Data Provider)
    
    ------------------------------
    For help, click: http://go.microsoft.com/fwlink?ProdName=Microsoft%20SQL%20Server&EvtSrc=MSSQLServer&EvtID=4064&LinkId=20476
    
    ------------------------------
    Server Name: ***
    Error Number: 4064
    Severity: 11
    State: 1
    Line Number: 65536
    
    
    ------------------------------
    Program Location:
    at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
    at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
    at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler,         TdsParserStateObject stateObj, Boolean& dataReady)
    at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject         stateObj)
    at System.Data.SqlClient.SqlInternalConnectionTds.CompleteLogin(Boolean enlistOK)
    at System.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean ignoreSniOpenTimeout,         TimeoutTimer timeout, Boolean withFailover)
    at System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance,         SqlConnectionString connectionOptions, SqlCredential credential, TimeoutTimer timeout)
    at System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(TimeoutTimer timeout, SqlConnectionString connectionOptions, SqlCredential credential, String newPassword,         SecureString newSecurePassword, Boolean redirectedUserInstance)
    at System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, SqlCredential credential, Object providerInfo,         String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString userConnectionOptions, SessionData reconnectSessionData)
    at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool,         DbConnection owningConnection, DbConnectionOptions userOptions)
    at System.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(DbConnection owningConnection, DbConnectionPoolGroup poolGroup, DbConnectionOptions userOptions)
    at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions,         DbConnectionInternal oldConnection, DbConnectionInternal& connection)
    at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry,         DbConnectionOptions userOptions)
    at System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry,         DbConnectionOptions userOptions)
    at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry)
    at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
    at System.Data.SqlClient.SqlConnection.Open()
    at Microsoft.SqlServer.Management.SqlStudio.Explorer.ObjectExplorerService.ValidateConnection(UIConnectionInfo ci, IServerType server)
    at Microsoft.SqlServer.Management.UI.ConnectionDlg.Connector.ConnectionThreadUser()

解决

option_u是用户的默认账号,根据报错判断是option_u账号的默认数据库出现异常,为了确认我们通过后端Windows认证登陆用如下SQL判断下:

SELECT
  SP.NAME,
  SP.TYPE_DESC,
  DB.STATE_DESC
FROM SYS.SERVER_PRINCIPALS AS SP
INNER JOIN SYS.DATABASES AS DB
  ON SP.DEFAULT_DATABASE_NAME = DB_NAME(DB.DATABASE_ID)
WHERE SP.NAME = 'OPTION_U'

结果没有返回!那这样看来是用户设置了一个不存在的数据库作为默认数据库,修复方式如下:

USE [master]
GO
ALTER LOGIN [option_u] WITH DEFAULT_DATABASE=[master]
GO

注意修复的前提是用户首先要能登陆数据库,当然着急的情况通过工单让后端处理也是可行的,但实际如果手边有SSMS客户端(如果没有可以从 这里下载)可以通过指定数据库解决

3.png

触发场景

问题的解决方法大家已经清楚了,但为什么会出现这种情况即用户为什么要设置一个不存在的库作为默认数据库呢?

为了了解背后的原因我们了解了用户的场景并做了如下测试:

  1. 实例生产后在控制台创建初始账号 test
    4.png
  2. 利用初始账号登陆登陆实例并创建数据库testdb

        SELECT SUSER_NAME() AS LOGIN_NAME
        GO
        CREATE DATABASE TESTDB
        GO

    5.png

  3. 把test的默认数据库改为testdb

        USE [master]
        GO
        ALTER LOGIN [test] WITH DEFAULT_DATABASE=[testdb]
        GO
  4. 删除testdb

        DROP DATABASE [testdb]

    6.png

  5. 再次尝试test登陆

7.png

至此原因也清楚了,用户并不是刻意设置一个不存在的数据库而是开始存在后来删除了

这里还有2个步骤值得分析和改进

  • 步骤3用户为什么要把test账号的默认数据库改为testdb

    
    这实际并不是一个通用的需求完全取决于应用,修改默认数据库后用户的链接字符串不需要配置DB参数,应用链接数据库后可以直接访问testdb下的object;反之也可以通过修改链接串的DB参数或者应用访问数据库对象的写法比如是DBNAME.Schema.Object(不支持link所以不需要servername),但这涉及的应用修改所以需要用户判断哪种更合适业务
    
  • 步骤4删除testdb

    我们知道SQLServer在一些情况会检查依赖关系,比如要删除某个账号但此账号在Trigger中有用到,那么删除就会失败并提示有引用依赖,但看起来login的default database没有在考虑范围内,微软虽然没做但考虑云产品的受众RDS可以通过一些方式实现给予用户更好的引导以提升体验,这也会作为后续的一个可改进点
        
相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情: https://www.aliyun.com/product/rds/sqlserver
目录
相关文章
|
SQL
天财商龙SQL查询ID登陆POS情况
SELECT * FROM [tcgem_client0001].[dbo].[TCB_POS] where cLoginEmpID ='000100011' --查询ID登陆POS情况  网名:浩秦; 邮箱:root#landv.pw; 只要我能控制一個國家的貨幣發行,我不在乎誰制定法律。
1338 0
|
SQL .NET Go
SQL Server 限制IP登陆(登陆触发器运用)
原文:SQL Server 限制IP登陆(登陆触发器运用) 一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 实现代码(SQL Codes) 补充说明(Addon) 疑问(Questions) 参考文献(References) 二.背景(Contexts)   在MySQL的mysql.User表保存了登陆用户的权限信息,Host和User字段则是关于登陆IP的限制。
1902 0
|
SQL 关系型数据库 Perl
|
SQL 关系型数据库 MySQL
sql点滴43—mysql允许用户远程登陆
方法1 局域网连接mysql报错: ERROR 1130: Host '192.168.0.220' is not allowed to connect to this MySQL server 解决方法: 可能是帐号不允许从远程登陆,只能在localhost。
1365 0
|
SQL 存储 Shell
无法使用SQL login去登陆SQL Server - 'Password did not match'
原文: 无法使用SQL login去登陆SQL Server - 'Password did not match' 出自:http://blogs.msdn.com/b/apgcdsd/archive/2011/02/01/sql-login-sql-server-password-did-not-match.aspx 问题描述: 在某一台机器上的management studio,始终无法使用SQL login去登陆SQL Server。
817 0
|
SQL Go 数据库
SQL server数据库用户映射到登陆用户
    最近有朋友的SQL server数据库意外中枪,几经周折,数据将数据库恢复到新环境。恢复后在数据库级别有用户名而实例级别则无相应的登陆用户。这在SQL server数据库中是一个比较普遍的情形。
1269 0