数据库安全与保护:关键技术解析与实践指南数据库作为现代信息系统的核心,其安全性与数据完整性直接影响业务的稳定性和可靠性。本文系统阐述数据库保护的五大核心模块:通过完整性约束保障数据逻辑正确性,利用触发器实现自动化监控,借助权限管理控制访问风险,依托事务与锁机制解决并发冲突,并结合备份恢复策
数据库作为现代信息系统的核心,其安全性与数据完整性直接影响业务的稳定性和可靠性。本文系统阐述数据库保护的五大核心模块:通过完整性约束保障数据逻辑正确性,利用触发器实现自动化监控,借助权限管理控制访问风险,依托事务与锁机制解决并发冲突,并结合备份恢复策略应对意外故障。文章以MySQL为例,结合代码示例与原理分析,为开发者提供从设计到运维的全链路防护方案。
本文聚焦数据库安全防护体系,深入解析关键技术实现路径:
列级约束主要指对列的类型、取值范围、精度等的约束,具体包括如下内容:
元组约束指元组中各个字段之间的相互约束。
表级约束指若干元组之间、关系之间的联系的约束。
在MySQL中,实体完整性是通过主键约束和候选键约束来实现的。
主键可以是表中的某一列,也可以是表中多个列所构成的一个组合。
其中,由多个列组合而成的主键也称为复合主键。
在MySQL中,主键列必须遵守如下一些规则:
主键约束可以在 CREATE TABLE 或 ALTER TABLE 语句中使用关键字“PRIMARY KEY”来实现。
其方式有两种:
注意:
如果主键仅由一个表中的某一列所构成,上述两种方法均可以定义主键约束。
如果主键是由表中多个列所构成的一个组合,则只能用上述第二种方法定义主键约束。
定义主键约束后,MySQL 会自动为主键创建一个唯一性索引,用于在查询中使用主键对数据进行快速检索,该索引名默认为 PRIMARY,也可以重新自定义命名。
任何时候,候选键的值必须是唯一的,且不能为 NULL。
候选键可以在 CREATE TABLE 或 ALTER TABLE 语句中使用关键字“UNIQUE”来定义,其实现方法与主键约束相似,同样可作为列或者表(关系)的完整性约束两种方式。
MySQL中候选键与主键之间存在以下几点区别:
外键声明的方式:
"reference_definition" 语法项的定义:
REFERENCES tbl_name (index_col_name, ...)
[ON DELETE reference_option]
[ON UPDATE reference_option]
index_col_name
的语法格式:
col_name [(length)] [ASC | DESC]
reference_option
的语法格式:
RESTRICT | CASCADE | SET NULL | NO ACTION
限制策略 级联策略 置空策略 不采取实施策略
例子:在数据库 mysql_test 中创建一个商品订单表 orders,该表包含的订单信息有:订单号 oder_id、订购商品名 order_product、订购商品类型 order_product_type、订购客户 id 号 cust_id、订购时间 order_date、订购价格 order_price、订购数量 order_amount。要求商品订单表 orders 中的所有订购客户信息均已在表 customers 中记录在册。
mysql> use mysql_test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> create table orders
-> (
-> order_id int not null auto_increment,
-> order_product char(50) not null,
-> order_product_type char(50) not null,
-> cust_id int not null,
-> order_date datetime not null,
-> order_price double not null,
-> order_amount int not null,
-> primart key (order_id),
-> foreign key (cust_id)
-> references customers(cust_id)
-> on delete restrict
-> on update restrict
-> );
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'key (order_id),
foreign key (cust_id)
references customers(cust_id)
on delete r' at line 10
mysql> desc customers;
+--------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+----------+------+-----+---------+----------------+
| cust_id | int | NO | PRI | NULL | auto_increment |
| cust_name | char(20) | YES | | NULL | |
| cust_sex | char(1) | YES | | M | |
| cust_city | char(10) | NO | | Beijing | |
| cust_address | char(50) | YES | | NULL | |
| cust_contact | char(50) | YES | | NULL | |
+--------------+----------+------+-----+---------+----------------+
6 rows in set (0.01 sec)
mysql> create table orders ( order_id int not null auto_increment, order_product char(50) not null, order_product_type char(50) not null, cust_id int not null, order_date datetime not null, order_price double not null, order_amount int not null, primary key (order_id), foreign key (cust_id) references customers(cust_id) on delete restrict on update restrict );
Query OK, 0 rows affected (0.05 sec)
mysql> desc orders;
+--------------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+----------+------+-----+---------+----------------+
| order_id | int | NO | PRI | NULL | auto_increment |
| order_product | char(50) | NO | | NULL | |
| order_product_type | char(50) | NO | | NULL | |
| cust_id | int | NO | MUL | NULL | |
| order_date | datetime | NO | | NULL | |
| order_price | double | NO | | NULL | |
| order_amount | int | NO | | NULL | |
+--------------------+----------+------+-----+---------+----------------+
7 rows in set (0.00 sec)
mysql>
当指定一个外键时,需要遵守下列原则:
CHECK (expr)
CONSTRAINT [symbol]
添加约束:ALTER TABLE 语句中使用 ADD CONSTRAINT子句
触发器(Trigger)是用户定义在关系表上的一类由事件驱动的数据库对象,也是一种保证数据完整性的方法。
触发器一旦定义,无须用户调用,任何对表的修改操作均由数据库服务器自动激活相应的触发器。
CREATE TRIGGER trigger_name trigger_time trigger_event
ON tbl_name FOR EACH ROW trigger_body
例子:在数据库 mysql_test 的表 customers 中创建一个触发器 customers_insert_trigger,用于每次向表 customers 插入一行数据时,将用户变量 str 的值设置为 “one customer added!”。
mysql> use mysql_test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> create trigger mysql_test.customers_insert_trigger after insert
-> on mysql_test.customers for each row set @str='one customer added!';
Query OK, 0 rows affected (0.02 sec)
mysql> insert into mysql_test.customers
-> values(null,'万华','F','长沙市','芙蓉区');
ERROR 1136 (21S01): Column count doesn't match value count at row 1
mysql> desc customers;
+--------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+----------+------+-----+---------+----------------+
| cust_id | int | NO | PRI | NULL | auto_increment |
| cust_name | char(20) | YES | | NULL | |
| cust_sex | char(1) | YES | | M | |
| cust_city | char(10) | NO | | Beijing | |
| cust_address | char(50) | YES | | NULL | |
| cust_contact | char(50) | YES | | NULL | |
+--------------+----------+------+-----+---------+----------------+
6 rows in set (0.01 sec)
mysql> alter table mysql_test.customers drop column cust_contact;
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> desc customers;
+--------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+----------+------+-----+---------+----------------+
| cust_id | int | NO | PRI | NULL | auto_increment |
| cust_name | char(20) | YES | | NULL | |
| cust_sex | char(1) | YES | | M | |
| cust_city | char(10) | NO | | Beijing | |
| cust_address | char(50) | YES | | NULL | |
+--------------+----------+------+-----+---------+----------------+
5 rows in set (0.01 sec)
mysql> insert into mysql_test.customers values(null,'万华','F','长沙市','芙蓉区');
Query OK, 1 row affected (0.00 sec)
mysql> select @str;
+---------------------+
| @str |
+---------------------+
| one customer added! |
+---------------------+
1 row in set (0.00 sec)
mysql>
DROP TRIGGER [IF EXISTS] [schema_name.] trigger_name
例子:删除数据库 mysql_test 中的触发器 customers_insert_trigger。
mysql> drop trigger if exists mysql_test.customers_insert_trigger;
Query OK, 0 rows affected (0.00 sec)
mysql>
例子:在数据库 mysql_test 的表 customers 中重新创建触发器 customers_insert_trigger,用于每次向表 customers插入一行数据时,将用户变量 str 的值设置为新插入客户的 id 号。
mysql> create trigger mysql_test.customers_insert_trigger after insert
-> on mysql_test.customers for each row set @str=new.cust_id;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into mysql_test.customers values(null,'曾伟','F','长沙市','芙蓉区');
Query OK, 1 row affected (0.00 sec)
mysql> select @str;
+------+
| @str |
+------+
| 911 |
+------+
1 row in set (0.00 sec)
mysql> select * from customers;
+---------+-----------+----------+-----------+--------------+
| cust_id | cust_name | cust_sex | cust_city | cust_address |
+---------+-----------+----------+-----------+--------------+
| 901 | 张三 | F | 北京市 | 武汉市 |
| 902 | 李四 | M | 武汉市 | 上海市 |
| 903 | 李四 | M | Beijing | 上海市 |
| 904 | 李四 | M | Beijing | 上海市 |
| 910 | 万华 | F | 长沙市 | 芙蓉区 |
| 911 | 曾伟 | F | 长沙市 | 芙蓉区 |
+---------+-----------+----------+-----------+--------------+
6 rows in set (0.00 sec)
mysql>
例子:在数据库 mysql_test 的表 customers 中创建一个触发器 customers_update_trigger,用于每次更新表 customers时,将该表中 cust_address 列的值设置为 cust_contact 列的值。
mysql> create trigger mysql_test.customers_update_trigger before update
-> on mysql_test.customers for each row
-> set new.cust_address=old.cust_contact;
ERROR 1054 (42S22): Unknown column 'cust_contact' in 'OLD'
mysql> alter table mysql_test.customers
-> add column cust_contact char(50) null;
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> create trigger mysql_test.customers_update_trigger before update on mysql_test.customers for each row set new.cust_address=old.cust_contact;
Query OK, 0 rows affected (0.01 sec)
mysql> update mysql_test.customers set cust_address='武汉市' where cust_name='曾伟';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select cust_address from mysql_test.customers where cust_name='曾伟';
+--------------+
| cust_address |
+--------------+
| NULL |
+--------------+
1 row in set (0.00 sec)
mysql> select * from customers;
+---------+-----------+----------+-----------+--------------+--------------+
| cust_id | cust_name | cust_sex | cust_city | cust_address | cust_contact |
+---------+-----------+----------+-----------+--------------+--------------+
| 901 | 张三 | F | 北京市 | 武汉市 | NULL |
| 902 | 李四 | M | 武汉市 | 上海市 | NULL |
| 903 | 李四 | M | Beijing | 上海市 | NULL |
| 904 | 李四 | M | Beijing | 上海市 | NULL |
| 910 | 万华 | F | 长沙市 | 芙蓉区 | NULL |
| 911 | 曾伟 | F | 长沙市 | NULL | NULL |
+---------+-----------+----------+-----------+--------------+--------------+
6 rows in set (0.00 sec)
mysql>
查看MySQL数据库的使用者账号
mysql> select user from mysql.user;
+------------------+
| user |
+------------------+
| root |
| mysql.infoschema |
| mysql.session |
| mysql.sys |
+------------------+
4 rows in set (0.01 sec)
CREATE USER user[IDENTIFIED BY [PASSWORD] 'password']
例子:在MySQL服务器中添加两个新的用户,其用户名分别为 zhangsan 和 lisi,他们的主机名均为 localhost,用户 zhangsan的口令设置为明文 123,用户 lisi的口令设置为对明文456使用 PASSWORD()函数加密返回的散列值。
# 查看 mysql 初始的密码策略
mysql> show variables like 'validate_password%';
+--------------------------------------+--------+
| Variable_name | Value |
+--------------------------------------+--------+
| validate_password.check_user_name | ON |
| validate_password.dictionary_file | |
| validate_password.length | 8 |
| validate_password.mixed_case_count | 1 |
| validate_password.number_count | 1 |
| validate_password.policy | MEDIUM |
| validate_password.special_char_count | 1 |
+--------------------------------------+--------+
7 rows in set (0.01 sec)
# 设置密码的验证强度等级,设置 validate_password_policy 的全局参数为 LOW
mysql> set global validate_password.policy=LOW;
Query OK, 0 rows affected (0.01 sec)
mysql> create user 'zhangsan'@'localhost' identified by '12345678';
Query OK, 0 rows affected (0.01 sec)
mysql> select md5(12345678); # MySQL 8.0+以上版本 password() 不可用
+----------------------------------+
| md5(12345678) |
+----------------------------------+
| 25d55ad283aa400af464c76d713c07ad |
+----------------------------------+
1 row in set (0.00 sec)
mysql> create user 'lisi'@'localhost' identified by '12345678';
Query OK, 0 rows affected (0.00 sec)
mysql>
官网:<https://dev.mysql.com/doc/refman/8.0/en/create-user.html>
CREATE USER
'jeffrey'@'localhost' IDENTIFIED WITH mysql_native_password
BY 'new_password1',
'jeanne'@'localhost' IDENTIFIED WITH caching_sha2_password
BY 'new_password2'
REQUIRE X509 WITH MAX_QUERIES_PER_HOUR 60
PASSWORD HISTORY 5
ACCOUNT LOCK;
DROP USER user [,user]...
例子:删除lisi用户
mysql> drop user lisi;
ERROR 1396 (HY000): Operation DROP USER failed for 'lisi'@'%'
mysql> drop user lisi@localhost;
Query OK, 0 rows affected (0.00 sec)
mysql>
RENAME USER old_user TO new_user [, old_user TO new_user] ...
例子:将用户 zhangsan 的名字修改成 wangwu
mysql> rename user 'zhangsan'@'localhost' to 'wangwu'@'localhost';
Query OK, 0 rows affected (0.00 sec)
mysql>
SET PASSWORD [FOR user] =
{
PASSWORD('new_password') | 'encrypted password'
}
例子:
mysql> set password for 'wangwu'@'localhost' = '88888888';
Query OK, 0 rows affected (0.00 sec)
mysql>
mysql> select user from mysql.user;
+------------------+
| user |
+------------------+
| root |
| mysql.infoschema |
| mysql.session |
| mysql.sys |
| wangwu |
+------------------+
5 rows in set (0.00 sec)
mysql> show grants for 'wangwu'@'localhost';
+--------------------------------------------+
| Grants for wangwu@localhost |
+--------------------------------------------+
| GRANT USAGE ON *.* TO `wangwu`@`localhost` |
+--------------------------------------------+
1 row in set (0.01 sec)
mysql>
GRANT
priv_type [(column_list)]
[, priv_type [(column_list)]] ...
ON [object_type] priv_level
TO user_specification [, user_specification] ...
[WITH GRANT OPTION]
*.*
" 表示所有数据库中的所有表user[IDENTIFIED BY [PASSWORD] 'password']
例子:授予用户 zhangsan 在数据库 mysql_test 的表 customers 上拥有对列 cust_id 和列 cust_name 的 SELECT 权限
➜ mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1105
Server version: 8.0.32 Homebrew
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> grant select (cust_id, cust_name) on mysql_test.customers to 'zhangsan'@'localhost';
ERROR 1410 (42000): You are not allowed to create a user with GRANT
mysql> select user from mysql.user;
+------------------+
| user |
+------------------+
| root |
| mysql.infoschema |
| mysql.session |
| mysql.sys |
| wangwu |
+------------------+
5 rows in set (0.00 sec)
mysql> rename user 'wangwu'@'localhost' to 'zhangsan'@'localhost';
Query OK, 0 rows affected (0.01 sec)
mysql> grant select (cust_id, cust_name) on mysql_test.customers to 'zhangsan'@'localhost';
Query OK, 0 rows affected (0.01 sec)
➜ mysql -uzhangsan -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1107
Server version: 8.0.32 Homebrew
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> select * from mysql_test.customers;
ERROR 1142 (42000): SELECT command denied to user 'zhangsan'@'localhost' for table 'customers'
mysql> select cust_id,cust_name from mysql_test.customers;
+---------+-----------+
| cust_id | cust_name |
+---------+-----------+
| 901 | 张三 |
| 902 | 李四 |
| 903 | 李四 |
| 904 | 李四 |
| 910 | 万华 |
| 911 | 曾伟 |
+---------+-----------+
6 rows in set (0.00 sec)
例子2:创建 liming 和 huang 两个用户,并设置对应的系统登录口令,同时授予他们在数据库 mysql_test 的表 customers 上拥有 SELECT 和 UPDATE 的权限。
mysql> grant select, update on mysql_test.customers to 'liming'@'localhost';
ERROR 1410 (42000): You are not allowed to create a user with GRANT
# mysql 8 最新的MySQL8不允许直接创建并授权,必须先让自己有GRANT权限,然后创建用户,再授权。
mysql> SELECT host,user,Grant_priv,Super_priv FROM mysql.user;
+-----------+------------------+------------+------------+
| host | user | Grant_priv | Super_priv |
+-----------+------------------+------------+------------+
| % | root | Y | Y |
| localhost | mysql.infoschema | N | N |
| localhost | mysql.session | N | Y |
| localhost | mysql.sys | N | N |
| localhost | zhangsan | N | N |
+-----------+------------------+------------+------------+
5 rows in set (0.00 sec)
mysql>
例子3:授予zhangsan 可以在数据库 mysql_test 中执行所有数据库操作的权限
mysql> grant all on mysql_test.* to 'zhangsan'@'localhost';
Query OK, 0 rows affected (0.01 sec)
例子4:授予 zhangsan 创建用户的权限
mysql> grant create user on *.* to 'zhangsan'@'localhost';
Query OK, 0 rows affected (0.01 sec)
mysql>
"priv_type" 的使用
例子:
~
➜ mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1173
Server version: 8.0.32 Homebrew
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> grant select,update on mysql_test.customers to 'zhou'@'localhost' identified by '123' with grant option;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'identified by '123' with grant option' at line 1
# mysql 8.0+ 报错 先创建用户 后授权
mysql> create user 'zhou'@'localhost' identified by '12345678';
Query OK, 0 rows affected (0.01 sec)
mysql> grant select,update on mysql_test.customers to 'zhou'@'localhost' identified by '12345678' with grant option;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'identified by '12345678' with grant option' at line 1
mysql> grant select,update on mysql_test.customers to 'zhou'@'localhost' with grant option;
Query OK, 0 rows affected (0.01 sec)
mysql>
REVOKE
priv_type [(column_list)]
[, priv_type [(column_list)]] ...
ON [object_type] priv_level
FROM user [, user] ...
REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user]...
例子:
mysql> revoke select on mysql_test.customers from 'zhou'@'localhost';
Query OK, 0 rows affected (0.00 sec)
mysql>
事务就是为保证数据的一致性而产生的一个概念和基本手段
例子:依据事物的ACID特性,分析并编写银行数据库系统中的转账事务T:从账户A转账S金额资金到账户B。
BEGIN TRANSACTION
read(A);
A=A-S;
write(A);
if(A<0) ROLLBACK
else {
read(B);
B=B+S
write(B);
COMMIT;
}
事务是并发控制的基本单位,保证事务的ACID特征是事务处理的重要任务,而事务的ACID特征可能遭到破坏的原因之一是多个事务对数据库的并发操作造成的。
完整性检验可以保证一个事务单独执行时,若输入的数据库状态是正确的,则其输出的数据库状态也是正确的。
当多个事务交错执行时,可能出现不一致问题,这也称为并发操作问题。
(1)丢失更新
(2)不可重复读
(3)读“脏”数据
并发控制机制就是用正确的方式调度并发操作,使一个用户事务的执行不受其他事务的干扰,从而避免造成数据的不一致性。
解决并发操作所带来的数据不一致性问题的方法有封锁、时间戳、乐观控制法和多版本并发控制等。
封锁的工作原理如下:
通常由粒度来描述封锁的数据单元的大小。
大多数高性能系统都选择折中的锁粒度,至于哪一层最合适,则与应用环境下事务量、数据量及数据的易变特征等都紧密相关。
封锁的级别又称为一致性级别或隔离度。
封锁带来的一个重要问题是可能引起“活锁”与“死锁”。
在并发事务处理过程中,由于锁会使一事务处于等待状态而调度其他事务处理,因而该事务可能会因优先级低而永远等待下去,这种现象称为“活锁”。
活锁问题的解决与调度算法有关,一种最简单的办法是“先来先服务”。
两个以上事务循环等待被同组中另一事务锁住的数据单元的情形,称为“死锁”。
在任何一个多任务程序设计系统中,死锁总是潜在的,所以在这种环境下的DBMS需要提供死锁预防、死锁检测和死锁发生后的处理技术与方法。
预防死锁的方法:
对待死锁的另一种办法是不去防止,而让其发生并随时进行检测,一旦检测到系统已发生了死锁再进行解除处理。
死锁检测可以用图论的方法实现,并以正在执行的事物为结点。
若一个调度等价于某一串行高度,即它所产生的结果与某一串行调度的结果一样,则说调度是可串行化的(Serializable)。
一组事务的串行调度不是唯一的,因而可串行化的调度也不是唯一的。
通常,在数据库系统中,可串行性就是并发执行的正确性准则,即当且仅当一组事务的并发执行调度是可串行化的,才认为它们是正确的。
采用两段封锁法(Two-Phase Locking,2PL)是一种最简单而有效的保障封锁其调度是可串行性的方法。
两段封锁法是事务遵循两段锁协议的调度方法。
协议就是所有事务都必须遵循的关于基本操作执行顺序的一种限制。
两段锁协议规定在任何一个事务中,所有加锁操作都必须在所有释放锁操作之前。
事务划分成如下两个阶段:
定理6.1:遵循两段锁协议的事务的任何并发调度都是可串行化的。
2PL 是可串行化的充分条件,不是必要条件,即存在不全是2PL的事务的可串行化调度。
数据库的实际使用过程中,存在着一些不可预估的因素:
数据库备份是指通过导出数据或者复制表文件的方式来制作数据库的复本
数据库恢复则是当数据库出现故障或遭到破坏时,将备份的数据库加载到系统,从而使数据库从错误状态恢复到备份时的正确状态。
数据库的恢复是以备份为基础的。它是与备份相对应的系统维护和管理操作。
SELECT * INTO OUTFILE 'file_name' export_options
| INTO DUMPFILE 'file_name'
其中,语法项“export_options” 的格式是:
[FIELDS
[TERMINATED BY 'string']
[[OPTIONALLY] ENCLOSED BY 'char']
[ESCAPED BY 'char']
]
[LINES TERMINATED BY 'string']
LOAD DATA INFILE 'file_name.txt'
INTO TABLE tbl_name
[FIELDS
[TERMINATED BY 'string']
[[OPTIONALLY] ENCLOSED BY 'char']
[ESCAPED BY 'char']
]
[LINES
[STARTING BY 'string']
[TERMINATED BY 'string']
]
例子:备份数据库mysql_test中表customers的全部数据。
➜ mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2354
Server version: 8.0.32 Homebrew
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> select * from mysql_test.customers
-> into outfile '/Users/qiaopengjun/backupfile.txt'
-> fields terminated by ','
-> optionally enclosed by ""
-> lines terminated by '?';
ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
mysql> show variables like '%secure_file_priv%';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| secure_file_priv | NULL |
+------------------+-------+
1 row in set (0.01 sec)
mysql> show global variables like "%datadir%";
+---------------+--------------------------+
| Variable_name | Value |
+---------------+--------------------------+
| datadir | /opt/homebrew/var/mysql/ |
+---------------+--------------------------+
1 row in set (0.02 sec)
mysql> select * from mysql_test.customers into outfile '/Users/qiaopengjun/backupfile.txt' fields terminated by ',' optionally enclosed by "" lines terminated by '?';
ERROR 2013 (HY000): Lost connection to MySQL server during query
No connection. Trying to reconnect...
Connection id: 8
Current database: *** NONE ***
Query OK, 6 rows affected (0.02 sec)
mysql> show variables like '%secure%';
+--------------------------+---------------------+
| Variable_name | Value |
+--------------------------+---------------------+
| require_secure_transport | OFF |
| secure_file_priv | /Users/qiaopengjun/ |
+--------------------------+---------------------+
2 rows in set (0.01 sec)
mysql>
mysql> select * from mysql_test.customers into outfile '/Users/qiaopengjun/backupfile.txt' fields terminated by ',' optionally enclosed by "" lines terminated by '?';
Query OK, 6 rows affected (0.01 sec)
mysql>
mysql复制表的两种方式:
第一、只复制表结构到新表 create table 新表 select * from 旧表 where 1=2 或者 create table 新表 like 旧表
第二、复制表结构及数据到新表 create table新表 select * from 旧表
homebrew/var/mysql on stable took 5.4s
➜ mysql --verbose --help | grep my.cnf
order of preference, my.cnf, $MYSQL_TCP_PORT,
/etc/my.cnf /etc/mysql/my.cnf /opt/homebrew/etc/my.cnf ~/.my.cnf
homebrew/var/mysql on stable
➜
brew services restart mysql
将备份数据导入到一个和customers表结构相同的空表 customers_copy 中
mysql> create table customers_copy select * from customers where 1=2;
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> show tables;
+----------------------+
| Tables_in_mysql_test |
+----------------------+
| customers |
| customers_copy |
| customers_view |
| orders |
| seller |
+----------------------+
5 rows in set (0.00 sec)
mysql> load data infile '/Users/qiaopengjun/backupfile.txt' into table mysql_test.customers_copy fields terminated by ',' optionally enclosed by "" lines terminated by '?';
Query OK, 6 rows affected (0.01 sec)
Records: 6 Deleted: 0 Skipped: 0 Warnings: 0
mysql> select * from customers_copy;
+---------+-----------+----------+-----------+--------------+--------------+
| cust_id | cust_name | cust_sex | cust_city | cust_address | cust_contact |
+---------+-----------+----------+-----------+--------------+--------------+
| 901 | 张三 | F | 北京市 | 武汉市 | NULL |
| 902 | 李四 | M | 武汉市 | 上海市 | NULL |
| 903 | 李四 | M | Beijing | 上海市 | NULL |
| 904 | 李四 | M | Beijing | 上海市 | NULL |
| 910 | 万华 | F | 长沙市 | 芙蓉区 | NULL |
| 911 | 曾伟 | F | 长沙市 | NULL | NULL |
+---------+-----------+----------+-----------+--------------+--------------+
6 rows in set (0.00 sec)
mysql>
数据库安全需通过多层次技术协同实现:完整性约束与触发器构成数据操作的前置校验层,权限管理构建访问控制的边界防护,事务机制保障并发场景下的数据一致性,备份策略则为灾难恢复提供兜底保障。开发实践中,建议遵循最小权限原则设计账号体系,对关键表启用行级锁减少并发冲突,并定期验证备份有效性。通过系统性防护策略,可显著降低数据泄露、逻辑错误及服务中断风险,为业务连续性提供坚实支撑。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!