SQL Server 2012中包含的数据库(Contained Database)探索

SQL Server 2012 引入了包含数据库,解决了传统数据库迁移时的问题。包含数据库是独立的,允许在不同服务器间轻松迁移,无需考虑排序规则和外部依赖。本文将探讨包含数据库的概念、创建步骤、用户迁移、备份与还原,帮助理解这一新特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SQL Server 2012引入了包含数据库(Contained Database),解决了与当前(非包含)数据库关联的某些问题和复杂性。包含的数据库不依赖于其所属服务器相关的配置、管理、排序规则和安全认证信息,因此可以在数据库实例间方便的移动和部署,使数据库的应用和实例分离开来,也使研发能够更好的集中在应用和功能本身。下面将从什么是包含数据库,如何创建包含数据库,如何将数据库转换为部分包含的数据库,如何将用户迁移为包含的数据库用户,以及如何备份和还原包含数据库等几个方面来熟悉一下2012的这个新特性。

  • 当前(非包含)的数据库所面临的问题
    在描述什么是包含数据库之前,先了解一下为什么会出现包含数据库。当前的数据库有一些问题,如下:
    1、在数据库迁移或部署的过程中一些信息会丢失
         当我们将数据库从一个SQL Server实例迁移到另一个实例是,诸如登陆、工作代理等信息将不能一起被迁移。因为这些信息有特殊用途,自创建后就常驻SQL Server实例。在新的SQL Server实例上重新创建这些任务将是一个耗时、易出错的过程。
    2、从应用开发转向部署
         在Server上部署应用时或许会遇到一些障碍,因为很有可能环境不匹配。例如,创建login时可能没权限,命令行实用工具(如“xp_cmdshell”)或许是禁用的,应用里用到的数据库排序规则或许和Server初始指定的(也可能是默认的)排序规则不同。
    3、应用管理的安全考量
         管理和维护单个数据库比较困难,因为login、job agent等信息是跨数据库实例访问的,因此,允许用户对整个实例授权将引起对其他数据库的不必要访问,进而导致安全隐患。
  • 什么是包含的数据库
    义如其名,它是一种自我包含的数据库。例如,它自带所有创建数据库时所需要的数据库设置及元数据信息。它独立于SQL Server实例,没有外部依赖关系,自带授权用户的自我包含机制。由于它独立于数据库实例,就使得在部署到不同服务器时数据库的排序规则不再是一个问题。
    一个包含的数据库,保留了所有数据库里必要信息和对象,如表、函数、限制、架构、类型等。它也存有所有数据库里的应用级对象,如登陆、代理作业、系统设置、链接服务器信息等。
    这种数据库带给我们的好处是,可以轻松地从一台Server搬移到另一台,并且不需要做任何额外配置就可以立即使用它,因为他们没有任何外部的依赖。
  • 4步创建包含的数据库
    步骤1、启用包含的数据库
    方法1: 使用 Management Studio 启用包含的数据库
    1.在对象资源管理器中,右击服务器名称,然后单击“属性”

    2.在“高级”页面上的“包含”部分中,将“启用包含的数据库”选项设置为“True”(默认为“False”)。

    3.单击“确定”。
    方法2: 使用T-SQL启用包含的数据库
    --Enabled Advanced options
    sp_configure 'show advanced', 1;
    RECONFIGURE WITH OVERRIDE;
    go
    --Enabled Database Containment
    sp_configure 'contained database authentication', 1;
    RECONFIGURE WITH OVERRIDE;
    go

    步骤2、创建一个数据库,并将它的包含类型设置为“部分”
    1. 创建一个名为“TestContainedDB”的数据库,然后右击该数据库并单击其属性

    2. 在“选项”一栏,将包含类型选择为“部分”,最后单击“确认”。


    步骤2也可以通过T-SQL实现:
    USE [master]
    GO
    
    /****** Object:  Database [TestContainedDB]    Script Date: 2012/4/18 16:31:14 ******/
    CREATE DATABASE [TestContainedDB]
     CONTAINMENT = PARTIAL
     ON  PRIMARY 
    ( NAME = N'TestContainedDB', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\TestContainedDB.mdf' , SIZE = 5120KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
     LOG ON 
    ( NAME = N'TestContainedDB_log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\TestContainedDB_log.ldf' , SIZE = 1024KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)
    GO
    
    ALTER DATABASE [TestContainedDB] SET COMPATIBILITY_LEVEL = 110
    GO
    
    IF (1 = FULLTEXTSERVICEPROPERTY('IsFullTextInstalled'))
    begin
    EXEC [TestContainedDB].[dbo].[sp_fulltext_database] @action = 'enable'
    end
    GO
    
    ALTER DATABASE [TestContainedDB] SET ANSI_NULL_DEFAULT OFF 
    GO
    
    ALTER DATABASE [TestContainedDB] SET ANSI_NULLS OFF 
    GO
    
    ALTER DATABASE [TestContainedDB] SET ANSI_PADDING OFF 
    GO
    
    ALTER DATABASE [TestContainedDB] SET ANSI_WARNINGS OFF 
    GO
    
    ALTER DATABASE [TestContainedDB] SET ARITHABORT OFF 
    GO
    
    ALTER DATABASE [TestContainedDB] SET AUTO_CLOSE OFF 
    GO
    
    ALTER DATABASE [TestContainedDB] SET AUTO_CREATE_STATISTICS ON 
    GO
    
    ALTER DATABASE [TestContainedDB] SET AUTO_SHRINK OFF 
    GO
    
    ALTER DATABASE [TestContainedDB] SET AUTO_UPDATE_STATISTICS ON 
    GO
    
    ALTER DATABASE [TestContainedDB] SET CURSOR_CLOSE_ON_COMMIT OFF 
    GO
    
    ALTER DATABASE [TestContainedDB] SET CURSOR_DEFAULT  GLOBAL 
    GO
    
    ALTER DATABASE [TestContainedDB] SET CONCAT_NULL_YIELDS_NULL OFF 
    GO
    
    ALTER DATABASE [TestContainedDB] SET NUMERIC_ROUNDABORT OFF 
    GO
    
    ALTER DATABASE [TestContainedDB] SET QUOTED_IDENTIFIER OFF 
    GO
    
    ALTER DATABASE [TestContainedDB] SET RECURSIVE_TRIGGERS OFF 
    GO
    
    ALTER DATABASE [TestContainedDB] SET  DISABLE_BROKER 
    GO
    
    ALTER DATABASE [TestContainedDB] SET AUTO_UPDATE_STATISTICS_ASYNC OFF 
    GO
    
    ALTER DATABASE [TestContainedDB] SET DATE_CORRELATION_OPTIMIZATION OFF 
    GO
    
    ALTER DATABASE [TestContainedDB] SET TRUSTWORTHY OFF 
    GO
    
    ALTER DATABASE [TestContainedDB] SET ALLOW_SNAPSHOT_ISOLATION OFF 
    GO
    
    ALTER DATABASE [TestContainedDB] SET PARAMETERIZATION SIMPLE 
    GO
    
    ALTER DATABASE [TestContainedDB] SET READ_COMMITTED_SNAPSHOT OFF 
    GO
    
    ALTER DATABASE [TestContainedDB] SET HONOR_BROKER_PRIORITY OFF 
    GO
    
    ALTER DATABASE [TestContainedDB] SET RECOVERY FULL 
    GO
    
    ALTER DATABASE [TestContainedDB] SET  MULTI_USER 
    GO
    
    ALTER DATABASE [TestContainedDB] SET PAGE_VERIFY CHECKSUM  
    GO
    
    ALTER DATABASE [TestContainedDB] SET DB_CHAINING OFF 
    GO
    
    ALTER DATABASE [TestContainedDB] SET DEFAULT_FULLTEXT_LANGUAGE = 2052 
    GO
    
    ALTER DATABASE [TestContainedDB] SET DEFAULT_LANGUAGE = 2052 
    GO
    
    ALTER DATABASE [TestContainedDB] SET NESTED_TRIGGERS = ON 
    GO
    
    ALTER DATABASE [TestContainedDB] SET TRANSFORM_NOISE_WORDS = OFF 
    GO
    
    ALTER DATABASE [TestContainedDB] SET TWO_DIGIT_YEAR_CUTOFF = 2049 
    GO
    
    ALTER DATABASE [TestContainedDB] SET FILESTREAM( NON_TRANSACTED_ACCESS = OFF ) 
    GO
    
    ALTER DATABASE [TestContainedDB] SET TARGET_RECOVERY_TIME = 0 SECONDS 
    GO
    
    ALTER DATABASE [TestContainedDB] SET  READ_WRITE 
    GO
    
    --------附:使用T_SQL将数据库转换为部分包含的数据库
    USE [master]
    GO
    ALTER DATABASE [TestContainedDB] SET CONTAINMENT = PARTIAL
    GO
    
    
  • 步骤3、创建一个包含的用户
    1. 新建用户


    2.创建用户名和密码,这里的用户名为TestUser,密码是Test@PWD1
    注意:密码需要达到复杂度要求,如英文字母、数字、特殊符号等,否则在创建时可能会遇到报错


    3. 成员身份选择“db_owner”



    通过T-SQL创建:
    USE [TestContainedDB]
    GO
    CREATE USER [TestUser] 
    WITH PASSWORD='Test@PWD1', 
    DEFAULT_SCHEMA=[dbo]
    GO
    创建好后,就可以在数据库的用户里看到:


    步骤4、 用包含的用户登录包含的数据库
    1.  在登录栏输入登录名(这里用的是TestUser)和密码(这里用的是Test@PWD1)


    2. 在连接属性栏(点击登陆界面的“选项”,展开后就可以看到)输入要连接的数据库名称(这里是TestContainedDB)


    3. 点击“连接”,即可登陆成功
  • 将非包含的数据库转换为包含的数据库
    这里,我先创建一个非包含的数据库(命名为:TestNonContainedDB),并建一张表和一个存储过程(如下截图),即为非包含数据库创建连个常见的对象。
    USE [master]
    GO
    
    /****** Object:  Database [TestNonContainedDB]    Script Date: 2012/4/19 10:27:16 ******/
    CREATE DATABASE [TestNonContainedDB]
     CONTAINMENT = NONE
     ON  PRIMARY 
    ( NAME = N'TestNonContainedDB', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\TestNonContainedDB.mdf' , SIZE = 5120KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
     LOG ON 
    ( NAME = N'TestNonContainedDB_log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\TestNonContainedDB_log.ldf' , SIZE = 1024KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)
    GO
    

    下面开始一步步将非包含的数据库转换成包含的数据库:
    1. 创建一个登录名和一个用户
    --Create a login on the server
    use master 
    CREATE LOGIN NonContainedUser
    WITH PASSWORD = 'PWD+12345'
    
    --Create a "non-contained" users for the login on the server
    USE TestNonContainedDB
    GO
    CREATE USER NonContainedUser FOR LOGIN NonContainedUser
    GO
    2. 先看看当前DB有哪些非包含的对象。由下图可见,忽略ROUTE,当前有1个非包含的数据库对象
    SELECT class_desc,feature_name,feature_type_name 
    FROM sys.dm_db_uncontained_entities
    

    对于非包含的用户,我们从下面可以看到只有1个:
    USE TestNonContainedDB
    GO
    SELECT dp.name 
    FROM sys.database_principals dp 
    JOIN sys.server_principals sp ON dp.sid = sp.sid
    WHERE dp.authentication_type = 1
      AND sp.is_disabled = 0 


    3. 将数据库转换为部分包含的数据库
    在对象资源管理器中,展开“数据库”,右键单击要转换的数据库(这里是TestNonContainedDB),然后单击“属性”,在“选项”页面上,将“包含类型”选项更改为“部分”,最后单击“确定”。或者使用如下T-SQL:
    USE [master]
    GO
    ALTER DATABASE TestNonContainedDB SET CONTAINMENT = PARTIAL
    GO
    4. 将用户迁移为包含的数据库用户
    迁移之前先看看当前的用户属性:


    现在执行下面的命令进行迁移:
    USE TestNonContainedDB
    GO
    EXEC sp_migrate_user_to_contained @username = N'NonContainedUser', 
                                      @rename = N'keep_name', 
                                      @disable_login = N'disable_login'
    执行之后再看看用户的属性,这是用户类型变成了带密码的SQL用户:


    再验证一下非包含的用户,由下图可见,将用户迁移为包含的数据库用户之后,对应的非包含用户就消失了;同时,对应的登录名也是被禁用状态。

    如果要将所有基于 SQL Server 登录名(启用的)的用户迁移到具有密码的包含的数据库用户,可在包含的数据库中执行下面命令:
    DECLARE @username sysname ;
    DECLARE user_cursor CURSOR
        FOR 
            SELECT dp.name 
            FROM sys.database_principals AS dp
            JOIN sys.server_principals AS sp 
            ON dp.sid = sp.sid
            WHERE dp.authentication_type = 1 AND sp.is_disabled = 0;
    OPEN user_cursor
    FETCH NEXT FROM user_cursor INTO @username
        WHILE @@FETCH_STATUS = 0
        BEGIN
            EXECUTE sp_migrate_user_to_contained 
            @username = @username,
            @rename = N'keep_name',
            @disablelogin = N'disable_login';
        FETCH NEXT FROM user_cursor INTO @username
        END
    CLOSE user_cursor ;
    DEALLOCATE user_cursor ;
    
    5. 用迁移的用户登录

  • 备份包含的数据库
    备份包含的数据库可以以备份非包含的数据库的方式(通过SSMS或T-SQL)来实现。唯一要注意的是,如果是通过包含的用户登录,则通过SSMS备份在右击数据库名称时会遇到如下问题(通过带登录名的SQL用户登录,就不会有此问题,当然也要有备份包含的数据库的权限):

    不过没关系,你可以通过T_SQL实现:
  • 还原包含的数据库

以上比较详细的介绍了包含的数据库的概念、创建、迁移、备份及还原等,其他相关信息,可以再参考MSDN:http://msdn.microsoft.com/zh-cn/library/ff929071.aspx 

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值