问题

最近公司很多数据库在上云,也有一部分在下云。这期间出现了很多问题,其中一个比较恶心的问题就是“孤立用户”。当数据库备份还原以后用以前的用户发现不能登录。一开始以为是登录账号没有创建,然后重新创建登录账号,然后再授权给数据库,此时又出错,说用户已经存在。我这才引起注意,开始搜索这个资料,原来这就是因为臭名昭著的孤立用户引起的。

什么是孤立的SQL用户?

那么孤立用户又是什么东西那?一个孤立用户就是一个数据库用户,同时没有SQL Server的登录权限。

在实际生产中有很多产生孤立用户的原因,最为主要的方式就是备份还原到不同的服务器实例时。还原数据库的时候回将数据库和用户一同还原到新的数据库上,但是服务器的登录账户却没有一同还原(也不需要这么做)。如果数据库相同服务器那么皆大欢喜,因为用户没有变。如果是不同服务器,此时登录账户中没有了数据库用的名称,即使你创建了相同的名称但是他们的ID也是不同的导致他们不能关联起来。此时就导致了数据库的用户被孤立,也不能访问。此时我们需要做的就是找出孤立用户修改或者删除重建。

下图中是外国网友列出可能的产生孤立用户的原因(很详细):

查找数据库中的孤立用户

我打算写一个脚本实现两个主要目的,一是找到一个实例内所有的孤立用户;第二是按需求删除这些用户。从网上找了不少脚本和博客发现都不能实现。所以我自己写了一个亲测可用。这个脚本的麻烦在于当删除用户时,这个用户拥有自己的对象,并且不能drop掉,只能先删除这个对象或者改变对象和用户之间的关系。在下面的例子中所有的用户拥有一个架构,脚本必须去处理这个用户的架构。用脚本实现把孤立用户存储到一个临时表内,然后根据临时表的用户信息删除架构和用户。

查找孤立用户的脚本

Use master
Go
Create Table #Orphans
(
RowID int not null primary key identity(1,1) ,
TDBName varchar (100),
UserName varchar (100),
UserSid varbinary(85)
)
SET NOCOUNT ON
DECLARE @DBName sysname, @Qry nvarchar(4000)
SET @Qry = ''
SET @DBName = ''
WHILE @DBName IS NOT NULL
BEGIN
SET @DBName =
(
SELECT MIN(name)
FROM master..sysdatabases
WHERE
/** to exclude named databases add them to the Not In clause **/
name NOT IN
(
'model', 'msdb',
'distribution'
) And
DATABASEPROPERTY(name, 'IsOffline') = 0
AND DATABASEPROPERTY(name, 'IsSuspect') = 0
AND name > @DBName
)
IF @DBName IS NULL BREAK Set @Qry = 'select ''' + @DBName + ''' as DBName, name AS UserName,
sid AS UserSID from [' + @DBName + ']..sysusers
where issqluser = 1 and (sid is not null and sid <> 0x0)
and suser_sname(sid) is null order by name'
Insert into #Orphans Exec (@Qry) End
Select * from #Orphans

如何删除用户(这部分切记酌情使用,先与使用人员或者DBA确认孤立用户已经用了再进行删除。并确认其架构对象不收影响)

接着上面的脚本,我们把用户从临时表中取出来进行循环处理。

Declare @SQL as varchar (200)
Declare @DDBName varchar (100)
Declare @Orphanname varchar (100)
Declare @DBSysSchema varchar (100)
Declare @From int
Declare @To int
Select @From = 0, @To = @@ROWCOUNT
from #Orphans
--Print @From
--Print @To
While @From <= @To
Begin
Set @From = @From + 1 Select @DDBName = TDBName, @Orphanname = UserName from #Orphans
Where RowID = @From Set @DBSysSchema = '[' + @DDBName + ']' + '.[sys].[schemas]'
print @DBsysSchema
Print @DDBname
Print @Orphanname
set @SQL = 'If Exists (Select * from ' + @DBSysSchema
+ ' where name = ''' + @Orphanname + ''')
Begin
Use ' + @DDBName
+ ' Drop Schema [' + @Orphanname + ']
End'
print @SQL
Exec (@SQL) Begin Try
Set @SQL = 'Use ' + @DDBName
+ ' Drop User [' + @Orphanname + ']'
Exec (@SQL)
End Try
Begin Catch
End Catch End Drop table #Orphans

脚本中需要注意的事项

  首先如果有些数据库的孤立用户不想处理那么在插入临时表时可以提前通过NOT IN语句排除数据库。在删除的孤立用户同时,也会删除孤立用户拥有的架构。需要引起注意。这个脚本将不会检查其他可能被用户拥有的对象。我已经在sql server 2005/2008/2014上进行了测试,请大家知悉。

总结

  在上云或者数据库迁移的时候一旦发现这类错误往往会出现一些难以预料的问题,我建议。可以先用查询的语句进行查询看看具体哪些用户是孤立用户,哪些需要区别对待,在进行其他处理。脚本是大大减少了自己挨个查询的时间,但是也提高了风险,请大家酌情使用。

孤立的SQL用户的更多相关文章

  1. SQL中迁移sql用户及密码脚本

    SQL中迁移sql用户及密码脚本   编写人:CC阿爸 2014-6-20 在日常SQL数据库的操作中,常常需要迁移数据库或重装服务器,这时候,一些之前建立的login账户,必须重新建立,以下可以通过 ...

  2. 模拟SQL用户 EXECUTE AS USER

    EXECUTE AS USER= @domain SELECT SUSER_NAME(), USER_NAME(); REVERT 以下语句可以模拟SQL用户,具体使用场景自行脑补.

  3. sql用户权限

    登录 1)右键根目录属性 点下面的sql server 和 windows 身份验证模式 2)安全性右键新建,选择登陆 去掉 那个"用户下次登陆是必须改密码" ,下面默认数据库改为 ...

  4. 【翻译】Flink Table Api & SQL — 用户定义函数

    本文翻译自官网:User-defined Functions  https://ci.apache.org/projects/flink/flink-docs-release-1.9/dev/tabl ...

  5. SQL——用户定义函数

    根据用户定义函数返回值的类型,可将用户定义函数分为如下三个类别: (1) 返回值为可更新表的函数 若用户定义函数包含单个 SELECT 语句且该语句可更新,则该函数返回的表也可更新,这样的函数称为内嵌 ...

  6. sql 用户相关命令

    查看所有用户 select distinct concat(user, '@', host,';') as userList from mysql.user; select  #查找 distinct ...

  7. SQL用户存在则更新不存在则插入

    1.添加索引(一般是唯一索引,我的是联合唯一索引): alter table T_Cart add unique index(goods_id,user_id); 2.SQL /* * 保存购物车(如 ...

  8. SQL 用户定义表类型,在存储过程里使用数据类型作參数

    在数据库编程里使用数据类型,能够提高代码的重用性.它们常常被使用在方法和存储过程中.使用数据类型,我们能够避免在存储过程里定义一串的參数,让人眼花缭乱,它就相当于面向对象语言里.向一个方法里传入一个对 ...

  9. SQL 用户定义表类型,在存储过程里使用表类型,表参数作参数

    .定义表类型SUTDENTTYPE,包含三个字段,分别对应学生表的NAME,SEX和PHONE.之所以如此创建,我是准备在插入新学生数据的存储过程中,以它为参数.   GO CREATE TYPE S ...

随机推荐

  1. 一个域名最多能对应几个IP地址?,一个IP地址可以绑定几个域名?

    一个域名最多能对应几个IP地址?,一个IP地址可以绑定几个域名?谢谢 xikeboy | 浏览 31055 次 推荐于2016-04-24 14:21:14 最佳答案 1.也就是说通常情况下一个域名同 ...

  2. UI 网页三原色

    配色宝典:设计师教你从零开始学习配色 三原色 : -------------------------------------------------------------    三原色     -- ...

  3. 安装新的int 9中断例程

    body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...

  4. JavaScript 字符串与对象互换

    对象转字符串: var str = JSON.stringify(obj); 字符串转对象: var str = JSON.parse(str);

  5. python生产随机数案例

    法1: list =list(string.lowercase + string.uppercase) + [str(i) for i in range(10)]FH=('!','@','#','$' ...

  6. 基于esp8266的智能台灯DIY

    研究esp8266已经很久了,特制作了一个智能灯, 代码如下,总结几点 一.关于arduino pro mini 的烧写方法 一定要在编译成功之后的下载提示出现的瞬间,单击复位按钮.才可进入烧写 二. ...

  7. python3 第十一章 - 数据类型之str(字符串)

    字符串是 Python 中最常用的数据类型,我们可以使用引号 ' 或 " 来创建字符串,例如: name = 'roy' sex = "男" 1.访问字符串中的值 Pyt ...

  8. 在Tomcat中配置连接池和数据源

    1.DataSource接口介绍 (1)DataSource 概述 JDBC1.0原来是用DriverManager类来产生一个对数据源的连接.JDBC2.0用一种替代的方法,使用DataSource ...

  9. jQuery的Nicescroll滚动条插件使用方法

    Nicescroll滚动条插件是一个非常强大的基于jQuery的滚动条插件,不需要增加额外的css,几乎全浏览器兼容.ie6+,实现只需要一段代码,侵入性非常小,样式可完全自定义,支持触摸事件,可在触 ...

  10. linux(ubuntu或Deepin等)+win7双系统升级win10出现grub解决办法

    1,set root=(hd0,msdos11) 2,set prefix=(hd0,msdos11)/boot/grub 3,insmod /boot/grub/i386-pc/normal.mod ...