目录
什么是数据库?
数据库是存储、检索和管理数据的系统化方式。它是现代信息技术领域中不可或缺的一部分,广泛应用于各种行业和日常生活中。数据库的核心功能是高效地组织和处理大量数据,以便用户和应用程序能够快速、准确地获取所需信息。
数据库的类型
1. 关系型数据库(RDBMS)
关系型数据库通过表格的形式来组织数据,每个表格包含一系列行(记录)和列(字段)。它们之间的数据通过关系进行连接,最常见的关系型数据库系统包括MySQL、Oracle、SQL Server和PostgreSQL等。
2. 非关系型数据库(NoSQL)
非关系型数据库不依赖于传统的表格关系模型,它们更适合处理非结构化或半结构化数据。NoSQL数据库可以进一步分为几种类型,包括文档型数据库(如MongoDB)、键值存储(如Redis)、列族存储(如Cassandra)和图形数据库(如Neo4j)。
MongoDB - 一个流行的开源NoSQL文档数据库,以其高性能、高可用性和易扩展性而闻名。MongoDB适用于处理大量的非结构化或半结构化数据。
MySQL - 一个广泛使用的开源关系型数据库管理系统,以其快速、可靠和易于使用而受到开发者的喜爱。
User Drivers - 这可能是一个用于自定义数据库驱动的选项,允许用户创建或使用特定的驱动程序来连接到特定的数据库。
Complete Support - 这可能表示该软件或服务提供了对所有列出数据库的全面支持。
Amazon Redshift - 亚马逊提供的一种完全托管的、可扩展的、宠物字节级数据仓库解决方案,用于数据仓库和分析。
Apache Cassandra - 一个分布式的NoSQL数据库,设计用于处理大量数据跨许多普通服务器,提供高可用性和没有单点故障。
Apache Derby - 一个开源的关系型数据库,可以嵌入到Java应用程序中,也可以作为独立的数据库服务器运行。
Apache Hive - 一个建立在Hadoop生态系统之上的数据仓库软件,可以用来进行数据摘要、查询和分析。
Azure SQL Database - 微软Azure云服务提供的关系型数据库服务,基于Microsoft SQL Server引擎。
Azure Synapse Analytics - 一个分析服务,用于数据仓库和大数据分析,支持即时BI和机器学习。
BigQuery - 谷歌云提供的完全托管的大数据分析服务,用于大规模数据分析和查询。
ClickHouse - 一个开源的列式数据库管理系统,用于在线分析处理(OLAP)。
CockroachDB - 一个分布式的SQL数据库,以其弹性、可扩展性和强一致性而闻名。
Couchbase Query - Couchbase提供的数据库查询服务,支持NoSQL和N1QL查询语言。
DocumentDB - 一种NoSQL数据库服务,用于存储、检索和管理文档数据。
Exasol - 一个高性能的分析数据库,用于处理大规模数据集。
Greenplum - 一个开源的、高度可扩展的数据仓库平台,基于PostgreSQL。
H2 - 一个轻量级的Java数据库,可以嵌入到Java应用程序中,也可以作为独立的数据库服务器运行。
HSQLDB - 一个纯Java编写的关系型数据库,可以作为嵌入式数据库或服务器使用。
IBM Db2 LUW - IBM Db2 for Linux, UNIX and Windows,是一个企业级的关系型数据库管理系统。
MariaDB - 一个流行的开源关系型数据库,是MySQL的一个分支,提供了许多增强的特性和改进。
Microsoft SQL Server - 微软开发的关系型数据库管理系统,提供广泛的数据管理功能和集成服务。
Microsoft SQL Server LocalDB - SQL Server的一个轻量级版本,主要用于开发和测试。
Oracle - 甲骨文公司开发的关系型数据库管理系统,广泛用于企业级应用。
PostgreSQL - 一个功能强大的开源关系型数据库系统,以其可靠性、健壮性和性能而闻名。
Redis - 一个开源的键值存储,通常用作数据库、缓存和消息代理。
SQLite - 一个轻量级的关系型数据库,设计为嵌入式、零配置、无服务器。
Snowflake - 一个云数据仓库平台,提供数据存储、数据仓库和分析服务。
下载安装Navicat,配置,省略;
MySQL简介:
MySQL是一个广泛使用的开源关系型数据库管理系统(RDBMS),它基于SQL(Structured Query Language)语言进行数据的管理和操作。MySQL由瑞典的MySQL AB公司开发,后被Sun Microsystems收购,最终在2010年被甲骨文(Oracle)公司收购。尽管所有权发生了变化,但MySQL仍然保持着开源的特性,并拥有一个活跃的开发者社区。
核心特性
-
高性能:MySQL以其高性能、可靠性和易用性而闻名。它能够处理大量的数据和高并发的访问,适用于各种规模的应用,从小型个人网站到大型企业级应用。
-
开源:作为一个开源项目,MySQL允许用户自由使用、修改和分发源代码。这促进了一个庞大的社区,为用户提供了大量的文档、教程和第三方工具。
-
跨平台:MySQL支持多种操作系统,包括Linux、Windows、macOS等,以及多种编程语言,如PHP、Python、Java、C++等,使其能够轻松集成到各种不同的技术环境中。
-
可扩展性:MySQL提供了多种存储引擎,如InnoDB、MyISAM、Memory等,每种存储引擎都有其特定的性能特点和功能,用户可以根据应用需求选择合适的存储引擎。
-
安全性:MySQL提供了强大的安全机制,包括用户权限管理、SSL加密连接、安全的身份验证插件等,以保护数据不被未授权访问。
-
事务支持:MySQL支持事务处理,确保数据的完整性和一致性。特别是InnoDB存储引擎,它支持ACID事务,可以进行崩溃恢复和多版本并发控制。
应用场景
-
网站开发:MySQL是许多流行的Web应用程序和内容管理系统(如WordPress、Drupal、Joomla等)的首选数据库。
-
企业应用:MySQL被用于存储和管理企业的关键数据,如客户信息、订单、财务记录等。
-
数据仓库:MySQL可以作为数据仓库的一部分,存储和分析大量数据,支持数据挖掘和商业智能应用。
-
嵌入式系统:由于其轻量级和可定制性,MySQL也适用于嵌入式系统和移动设备。
-
科研和教育:MySQL因其易用性和广泛的文档支持,常被用于科研和教育领域,帮助学生和研究人员学习数据库管理和数据分析。
MySQL基本操作
mysql的启动:
1.打开命令行:
cmd
2.输入mysql -hlocalhost -uroot -p;
在命令行中,输入了mysql操作后可能出现报错,说不存在mysql命令。
1打开我的电脑
2点开属性---点开高级系统设置---点击左下角的环境变量
3在系统变量中找到path:点击添加浏览自己的MySQL文件下的bin文件,添加进去。
4点确定 点确定
配置好之后
再次输入 mysql -hlocalhost -uroot -p;初始密码一般为root
其他的操作:
1.查询时间:select now();
2.查询当前用户:select user();
3.查询数据库版本:select version();
4.列出数据库:show databases;
5.选择数据库:use databaseName;
6.建立数据库:create database databaseName;
7.查看新创建的数据库信息:show create database databaseName;
8.删除数据库:drop database databaseName;
1.查询时间:select now();
2.select user();
3.查询数据库版本:select version();
4.列出数据库:show databases;
5.选择数据库:use databaseName;
6.建立数据库:create database databaseName;
7.查看新创建的数据库信息:show create database databaseName;
8.删除数据库:drop database databaseName;
9.查看数据表存储引擎:show engines;(由此可以感受到mysql数据库一个特点可扩展性)
Engine:存储引擎的名称。
Support:存储引擎的支持级别。可以是
YES
(支持)、DEFAULT
(默认存储引擎)或者NO
(不支持)。Comment:对存储引擎的简短描述,包括它的一些主要特性和用途。
Transactions:指示该存储引擎是否支持事务处理。
YES
表示支持,NO
表示不支持。XA:表示存储引擎是否支持分布式事务(使用XA协议)。
YES
表示支持,NO
表示不支持。Savepoints:指示存储引擎是否支持保存点,这是一种事务回滚的机制,允许部分回滚事务。
YES
表示支持,NO
表示不支持。具体到每个存储引擎的说明:
InnoDB:InnoDB是MySQL的默认存储引擎,支持事务、行级锁定和外键。它是最常用的存储引擎之一,因为它提供了高级的数据完整性和并发控制。
MRG_MYISAM:这是一个合并存储引擎,可以将多个相同的MyISAM表集合并在一起。它不支持事务和保存点。
MEMORY:这个存储引擎使用内存作为存储介质,数据存储在哈希表中。它不适合存储大量数据,但适用于临时表和快速访问。
BLACKHOLE:这个存储引擎类似于
/dev/null
,写入其中的数据会立即消失。它通常用于测试或作为不实际存储数据的引擎。MyISAM:MyISAM是MySQL早期的默认存储引擎,不支持事务和行级锁定。它适用于读取密集型的表,并提供了全文搜索的功能。
CSV:CSV存储引擎将数据存储在逗号分隔值文件中。它不支持事务和保存点。
ARCHIVE:这个存储引擎用于存储大量不常变更的数据,如归档数据。它不支持事务和保存点。
PERFORMANCE_SCHEMA:这不是一个真正的存储引擎,而是一个用于收集MySQL服务器性能数据的组件。
FEDERATED:这是一个联合存储引擎,允许你将不同的MySQL服务器作为一个单一的数据库进行查询和管理。它不支持事务和保存点。
10.列出表格:show tables;
11.创建表:CREATE TABLE tableName(
c_num int (11) not null unique primary key auto_increment,
c_name varchar (50),
c_contact varchar (50),
c_city varchar (50),
c_birth datetime not null
);
12.查看表结构:desc tableName;
13.查看表中所有的内容:select * from tableName;
IDEA连接数据库:
下载驱动
可以首先点一下左下角的 Test Connection,成功之后 直接点ok或者apply;
注意:如果出现连接成功后,创建的数据表没有出现,可以使用refresh刷新一下,可能是因为idea没有反应过来。
这样IDEA就连接上了mysql数据库,你在这里操作,mysql数据库里面的数据同样也会同时更新。
在具体的数据库里面在新建新的Query Console
或者直接选择更改。
数据库中表与表之间的关系:
一对多关系:
一张表A中的一条记录可以对应另一张表B中的多条记录,另一张表B中的一条记录只能对应一张表A中的一条记录
例如:
表A:学生表student(子表)
id name class_id(外键非空:班级id)
1001 张三 111
1002 张四 222
1003 王五 111
1004 赵六 111
班级表class(父表)
id name
111 class1
222 class2
一个班级对应多个学生,一个学生只能对应一个班级
SELECT
s.id,s.name,c.name as className
FROM
student s
JOIN
class c
ON
s.class_id=c.id
WHERE
s.name LIKE '张%'
在一对多关系中需要注意以下几点:
添加数据时,先添加父表(class)记录,再添加子表(student)记录;(比如增加一个学生而他的班级是class3,父表没有该班级需要先添加)
删除数据时,先删除子表(student)记录,再删除父表(class)记录;(比如删除一个学生且只有他的班级是class2,先删除学生后再删除父表的class2)
一对一关系:
一对一的关系就是一种特殊的多对多的关系,一张表A中的一条记录只能对应另一张表B中的一条记录,另一张表B中的一条记录也只能对应一张表A中的一条记录
多对多关系:
一张表A中的一条记录可以对应另一张表B中的多条记录,另一张表B中的一条记录也可以对应一张表A中的多条记录
学生表student:
id name
1001 张三
1002 张四
1003 王五
1004 赵六
课程表course:
id name
111 java
222 mysql
一个学生可以选择多门课程,一门课程可以被多个学生选择
学生课程关系表student_course_relation(关系表)
student_id course_id
1001 111
1001 222
1002 111
1002 222
事务
什么是事务?
数据库中的事务是指对数据库执行一批操作,在同一个事务当中,这些操作最终要么全部执行成功,要么全部失败,不会存在部分成功的情况。
事务是一个原子操作。是一个最小执行单元。可以甶一个或多个SQL语句组成
在同一个事务当中,所有的SQL语句都成功执行时,整 个事务成功,有一个SQL语句执行失败,整个事务都执行失败。
举个例子:
比如A用户给B用户转账100操作,过程如下:
从A账户扣100
给B账户加100
如果在事务的支持下,上面最终只有2种结果:
操作成功:A账户减少100;B账户增加100
操作失败:A、B两个账户都没有发生变化
如果没有事务的支持,可能出现错:A账户减少了100,此时系统挂了,导致B账户没有加上100,而A账户凭空少了100。
事务的几个特性(ACID) -重点
原子性(Atomicity)
事务的整个过程如原子操作一样,最终要么全部成功,或者全部失败,这个原子性是从最终结果来看的,从最终结果来看这个过程是不可分割的。
一致性(Consistency)
一个事务必须使数据库从一个一致性状态变换到另一个一致性状态。首先回顾一下一致性的定义。所谓一致性,指的是数据处于一种有意义的状态,这种状态是语义上的而不是语法上的。最常见的例子是转帐。例如从帐户A转一笔钱到帐户B上,如果帐户A上的钱减少了,而帐户B上的钱却没有增加,那么我们认为此时数据处于不一致的状态。
从这段话的理解来看,所谓一致性,即,从实际的业务逻辑上来说,最终结果是对的、是跟程序员的所期望的结果完全符合的
隔离性(Isolation)
一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。这里先提一下事务的隔离级别:
读未提交:read uncommitted
读已提交:read committed
可重复读:repeatable read
串行化:serializable
持久性(Durability)
一个事务一旦提交,他对数据库中数据的改变就应该是永久性的。当事务提交之后,数据会持久化到硬盘,修改是永久性的。
什么是JDBC?
主要的技术文章:
JDBC全集http://t.csdnimg.cn/VbLH4
IDEA导入jar包https://blog.csdn.net/weixin_46028577/article/details/106342938
JDBC(Java Database Connectivity)是一个Java API,它定义了客户端如何连接和执行数据库操作。JDBC为数据库访问提供了一种独立于平台和数据库的方法,允许Java程序与多种数据库进行交互。
JDBC API 包含一组接口和类,它们位于java.sql
和javax.sql
包中。通过这些接口和类,开发者可以编写数据库应用程序,而不需要关心底层数据库的细节。JDBC驱动程序充当了Java应用程序和数据库之间的桥梁,负责将数据库操作请求从Java代码转换为特定数据库系统能够理解的调用。
JDBC API 的主要组件:
Driver Manager:负责管理JDBC驱动程序。它提供了一组方法来加载驱动程序、建立数据库连接和处理连接属性。
Connection:表示与数据库的连接。通过这个接口,可以创建
Statement
、PreparedStatement
或CallableStatement
对象,以及管理事务。Statement:用于执行静态SQL语句并返回结果。它可以用于执行不带参数的查询或更新。
PreparedStatement:继承自
Statement
,用于执行带参数的预编译SQL语句。这种类型的语句可以提高性能,因为它们可以被编译并重用。CallableStatement:用于执行存储在数据库中的SQL存储过程。
ResultSet:表示从数据库查询返回的结果集。它提供了一系列的操作来遍历结果集、获取数据和处理元数据。
实现的具体步骤:
1、导入驱动jar包 2、注册驱动 3、获取数据库的连接对象 4、定义sql语句 5、获取执行sql语句的对象 6、执行sql并接收返回结果 7、处理结果 8、释放资源
如何导入Jar包:
方式一:
首先搜索你想要的jar包:
Maven Repository: Search/Browse/Explore (mvnrepository.com)
然后在你的idea里面新建一个目录,叫做lib
然后把你下载的jar包导入进去,
然后在点击add as library
最后就是成功导入了你的jar包。
方式二:
打开 project structure,可以在file之中直接查找,也可以直接按ctrl+alt+shift+s快捷键输入。
打开之后Dependencies-> 加号 -> Jars or directories
找到所需导入的Jar包,点击apply 即可。
JDBC具体操作:
package org.example; // 定义了代码的包名为org.example
import java.sql.*; // 导入java.sql包下的所有类和接口,用于数据库操作
public class JDBCDemo {
public static void main(String[] args) throws Exception { // 主方法,声明抛出Exception异常
// 声明Connection对象,用于建立与数据库的连接
Connection con;
// 指定JDBC驱动类名
String driver = "com.mysql.jdbc.Driver";
// 数据库的URL,包括数据库类型、IP地址、端口号和数据库名
String url = "jdbc:mysql://localhost:3306/acm";
// 数据库的用户名
String user = "root";
// 数据库的密码
String password = "123456";
try { // 定义一个try块,用于捕获可能出现的异常
// 加载数据库驱动类
Class.forName(driver);
// 通过DriverManager.getConnection方法建立与数据库的连接
con = DriverManager.getConnection(url, user, password);
// 检查连接是否成功,如果没有关闭则打印成功信息
if (!con.isClosed()) {
System.out.println("Succeeded connecting to the Database!");
}
// 创建Statement对象,用于执行SQL语句
Statement statement = con.createStatement();
// 定义要执行的SQL查询语句
String sql = "select * from tbl_message";
// 执行SQL查询,并将结果存储在ResultSet对象中
ResultSet rs = statement.executeQuery(sql);
// 打印查询结果的表头
System.out.println("-----------------");
System.out.println("执行结果如下所示:");
System.out.println("-----------------");
System.out.println("姓名" + "\t" + "职称");
System.out.println("-----------------");
// 遍历ResultSet对象,逐行读取数据
String job = null;
String id = null;
while (rs.next()) {
// 通过ResultSet的getString方法获取指定列的值
job = rs.getString("id");
id = rs.getString("title");
// 打印读取的数据
System.out.println(id + "\t" + job);
}
// 关闭ResultSet对象
rs.close();
// 关闭数据库连接
con.close();
} catch (ClassNotFoundException e) { // 捕获找不到数据库驱动类的异常
// 打印异常信息
System.out.println("Sorry, can't find the Driver!");
e.printStackTrace(); // 打印异常的堆栈信息
} catch (SQLException e) { // 捕获SQL异常,如连接失败、执行SQL语句错误等
// 打印异常的堆栈信息
e.printStackTrace();
} catch (Exception e) { // 捕获其他类型的异常
// 这里应该添加更具体的异常处理逻辑
e.printStackTrace();
} finally { // finally块中的代码无论是否发生异常都会执行
// 打印数据库数据成功获取的信息
System.out.println("数据库数据成功获取!!");
}
}
}
事务操作(实例):
数据表:
package org.example;
import java.sql.*;
public class BankTransferDemo {
//在较新的JDBC驱动版本中,特别是从MySQL Connector/J 5.1开始
// JDBC驱动自动注册自己到java.util.logging日志框架
// 因此在代码中不需要显式地调用Class.forName()来加载和注册JDBC驱动。这是为了简化使用JDBC驱动的过程。
// 数据库连接信息
private static final String URL = "jdbc:mysql://localhost:3306/acm"; // 数据库URL
private static final String USER = "root"; // 数据库用户名
private static final String PASSWORD = "123456"; // 数据库密码
public static void main(String[] args) {
// 定义转账的源账户ID、目标账户ID和转账金额
int fromAccountId = 1;
int toAccountId = 2;
double amount = 300.00;
// 通过JDBC连接到数据库
try (Connection connection = DriverManager.getConnection(URL, USER, PASSWORD)) {
// 关闭自动提交,以便手动控制事务
connection.setAutoCommit(false);
// 检查源账户是否有足够的余额进行转账
checkBalance(connection, fromAccountId, amount);
// 从源账户扣款
withdrawFunds(connection, fromAccountId, amount);
// 假设这里可能会发生异常,例如除以零的错误
// int t = 5 / 0; // 这行代码会被注释掉,因为它会导致异常
// 向目标账户存款
depositFunds(connection, toAccountId, amount);
// 插入一条转账记录到数据库
insertTransferRecord(connection, fromAccountId, toAccountId, amount);
// 提交事务,使所有更改生效
connection.commit();
System.out.println("Transfer completed successfully.");
} catch (SQLException e) {
// 如果在处理过程中发生SQL异常,则打印错误信息,并回滚事务
System.out.println("Transfer failed. Transaction rolled back.");
e.printStackTrace();
}
}
// 检查账户余额是否充足
private static void checkBalance(Connection connection, int accountId, double amount) throws SQLException {
String sql = "SELECT balance FROM accounts WHERE account_id = ?"; // SQL查询语句
try (PreparedStatement statement = connection.prepareStatement(sql)) {
statement.setInt(1, accountId); // 设置查询参数
try (ResultSet resultSet = statement.executeQuery()) { // 执行查询并获取结果集
if (!resultSet.next() || resultSet.getDouble("balance") < amount) {
// 如果账户不存在或余额不足,抛出异常
throw new SQLException("Insufficient funds.");
}
}
}
}
// 从指定账户扣款
private static void withdrawFunds(Connection connection, int accountId, double amount) throws SQLException {
String sql = "UPDATE accounts SET balance = balance - ? WHERE account_id = ?"; // SQL更新语句
try (PreparedStatement statement = connection.prepareStatement(sql)) {
statement.setDouble(1, amount); // 设置扣款金额
statement.setInt(2, accountId); // 设置账户ID
statement.executeUpdate(); // 执行更新操作
}
}
// 向指定账户存款
private static void depositFunds(Connection connection, int accountId, double amount) throws SQLException {
String sql = "UPDATE accounts SET balance = balance + ? WHERE account_id = ?"; // SQL更新语句
try (PreparedStatement statement = connection.prepareStatement(sql)) {
statement.setDouble(1, amount); // 设置存款金额
statement.setInt(2, accountId); // 设置账户ID
statement.executeUpdate(); // 执行更新操作
}
}
// 插入一条转账记录
private static void insertTransferRecord(Connection connection, int fromAccountId, int toAccountId, double amount) throws SQLException {
String sql = "INSERT INTO transfers (from_account_id, to_account_id, amount) VALUES (?, ?, ?)"; // SQL插入语句
try (PreparedStatement statement = connection.prepareStatement(sql)) {
statement.setInt(1, fromAccountId); // 设置转出账户ID
statement.setInt(2, toAccountId); // 设置转入账户ID
statement.setDouble(3, amount); // 设置转账金额
statement.executeUpdate(); // 执行插入操作
}
}
}
注意:
1.url: jdbc:mysql://localhost:3306/db_2 ?servierTimezone=UTC 加时区 2.4.3版本之前
2.
com.mysql.jdbc.Driver
:这是较旧版本的驱动程序,属于MySQL Connector/J 5.x系列。在这个版本中,驱动程序类被称为com.mysql.jdbc.Driver
。
com.mysql.cj.jdbc.Driver
:这是更新版本的驱动程序,属于MySQL Connector/J 6.x和更高版本。
自主学习 :数据库连接池技术并实践
数据库连接池技术是一种在应用程序和数据库之间管理数据库连接的机制,它允许应用程序重复使用现有的数据库连接,而不是每次需要访问数据库时都创建新的连接。这种技术可以显著提高应用程序的性能和响应速度,同时减少资源消耗和系统开销。
为什么需要数据库连接池技术?
- 创建新的数据库连接是一个资源密集型的过程,涉及到网络通信和安全认证等步骤,这些步骤在高并发场景下会导致显著的性能开销。
- 数据库连接池通过预先创建并维护一定数量的数据库连接来避免频繁的连接创建和关闭,从而减少了系统资源的消耗和提高了效率。
- 连接池还可以帮助避免资源泄露,因为它可以通过超时机制强制回收长时间被占用的连接。
数据库连接池的基本原理
- 连接池维护着一组已经建立的数据库连接,当应用程序需要访问数据库时,可以从连接池中获取一个连接,使用完毕后再将其释放回连接池。
- 连接池中的连接可以是活跃的(正在使用中)或空闲的(未被使用),连接池会根据预先设定的策略来管理这些连接,如限制最大连接数、最小连接数以及连接的超时时间等。
数据库连接池的优点
- 资源高效利用:由于连接可以被重用,减少了创建和关闭连接的开销,提高了系统的整体效率。
- 更快的系统响应速度:应用程序可以直接使用连接池中的现有连接,避免了建立新连接所需的时间延迟。
- 统一的连接管理:连接池提供了统一的接口来管理数据库连接,简化了应用程序的数据库访问逻辑。
- 避免连接泄露:连接池可以监控连接的使用情况,并在连接不再需要时自动回收,防止了连接泄露和资源浪费。
数据库连接池的实现方式
- 可以通过编程手动实现一个简单的数据库连接池,或者使用现成的数据库连接池框架,如C3P0、 Druid等。
- 实现时需要考虑连接的创建、分配、回收、超时处理以及连接的有效性检测等关键功能。
数据库连接池的高级特性
高级连接池可能包括连接的负载均衡、故障转移、自动重连机制以及与中间件的集成等特性,以提供更稳定和高效的数据库访问服务。