传统运维学习OceanBase多少会因为不熟悉新事物有些担心,然而换OceanBase就跟换一辆高级车一样区别不会太多。由于大部分人还没接触过OceanBase,这里介绍OceanBase运维还有点早。不如先分享一下如果要安装OceanBase需要具备哪些经验。对于老司机而言,下面的内容都会显得很浅显,可以直接拉到最后。​


数据库服务器


对于主要使用​​IOE​​​架构的企业,估计很少用普通商用服务器去部署数据库,所以​​DBA​​或者运维都很少去想一个数据库服务器要做哪些事情。所以当发现要把数据库搬到普通服务器上时,会有非常多的担心。如性能行不行、可靠性高不高、怎么做高可用、出事了谁担责任。这种担心也很正常,在早期阿里巴巴DBA探索在普通服务器上部署ORACLE时,也是内部争论很多,有很多担心。从这篇旧文《ORACLE Fusion-io最佳实践 http://www.hellodb.net/2011/02/oracle-fusion-io.html》可以看出。

选用商用服务器后,性能主要取决于CPU和IO。这里稍微深入的分析一下。

CPU

普通服务器的​​CPU​​是​​x86​​架构架构.其单HZ处理能力已经超过IBM的Power序列。不过Power序列的内存访问使用​​SMP​​结构,所有CPU访问内存速度都一致,​​x86​​服务器访问内存采用​​NUMA​​结构,CPU和内存的节点一一对应,跨节点访问性能会有下降(有点分布式存储的感觉),并且还有不同内存节点间同步成本。所以随着CPU增长,​​x86​​的线性增长能力可能不如​​Power​​序列。当然单纯比较CPU意义也不大,还要综合稳定性看。不过使用x86服务器做数据库服务器,一个经验就是关闭NUMA

NUMA关闭方法也很简单,在/etc/grub.confkernel一行后添加了numa=off,重启服务器就生效。所以,如果要准备OceanBase数据库服务器,也请先关闭NUMA

此外对于​​CPU​​​还有描述也需要了解一下。物理CPU指真实的CPU硬件,通常说的几路就是指这个个数,Linux下用不同​​Physical ID​​​区分。核心数(​​Core​​​)是物理CPU的内部划分。Intel的​​CPU​​​支持超线程技术,每个​​Core​​​可以变成两个逻辑​​CPU​​。

# 查看物理CPU个数
cat /proc/cpuinfo | grep 'physical id' |
​​sort​​ | uniq |wc -l
# 查看核心个数
cat /proc/cpuinfo | grep 'core id' |
​​sort​​​| uniq |wc -l
# 查看逻辑CPU个数
cat /proc/cpuinfo | grep 'processor' |sort ​​​|​wc -l


#lscpu

Architecture:          x86_64

CPU op-mode(s):        32-bit, 64-bit

Byte Order:            Little Endian

CPU(s):                24

On-line CPU(s) list:   0-23

Thread(s) per core:    2​​Core(s) per soc​​ket:    6​​Socket(s):             2

NUMA node(s):          1

......



日常交流中我们说的CPU个数多是指逻辑CPU个数。OceanBase进程启动后,会获取服务器的逻辑CPU个数,扣除2个给OS,其他都声称是自己的。OceanBase的测试环境建议CPU个数不要低于32个。

内存

linux的内存页大小是​​4K​​​,如今内存都很大,256G也不算什么,为了管理这么多内存页,OS的页目录也会非常大。所以Linux从内核2.6版本后支持一种大页技术,页大小为​​2M​​​。后来​​RHEL 6​​​又引入透明大页技术,前者就叫传统大页技术。二者区别是传统大页管理是预分配、透明大页管理是动态分配。使用透明大页时,可能在分配失败时内核会尝试直接回收和压缩其他内存导致​​sys​​飙高,系统性能可能出现大幅抖动甚至重启。ORACLE的安装文档就建议使用传统大页,关闭透明大页。OceanBase也是同理。

#在线关掉方法:​​echo never > /sys/kernel/mm/transparent_hugepage/enabled​​​echo never > /sys/kernel/mm/transparent_hugepage/defrag​

存储

存储常常是数据库的性能瓶颈,也是运维最大的担忧。商用服务器当然也支持连接FC存储。不过如今这早已不是唯一选择。如今使用SSD方案的IO性能已经可以远远超过存储。SSD的类型很多,早期使用SSD的时候会有一个擦写次数的限制(寿命问题)。数据库IO通常有两种类型特点,一是随机​​IO​​​,一是顺序​​IO​​​。ORACLE数据库的数据读写多是随机​​IO​​​比较多,所以对​​SSD​​​寿命有要求。OceanBase读写有随机​​IO​​​,不过次数相对来说很少(因为OceanBase使用LSM模型,写首先是尽可能的缓存在内存里,不及时落盘)。此外就是密集的大IO,可能也有很多顺序IO。总体来说OceanBase对​​SSD​​寿命非常友好。

​SSD​​​的存储流程是数据经过设备物理接口,然后是逻辑协议转换为指令协议。这其中物理接口有​​SATA​​​、​​PCIE​​​的区别,逻辑协议有​​AHCI​​​和​​NVME​​​之分。​​NVME​​​相对于​​AHCI​​​具有低延时、高​​IOPS​​、低功耗等。


物理接口

逻辑协议

指令协议

SATA

AHCI

ATA

M.2/PCIe

AHCI

ATA

PCIe/U2

NVMe

NVMe

就实际使用体验而言,使用​​SATA​​​接口的​​SSD​​​,​​IO​​​依然很可能是数据库的性能瓶颈,而使用​​PCIe​​​接口搭配​​NVMe​​​协议的​​SSD​​​时,数据库性能瓶颈通常又转移到​​CPU​​​了。OceanBase生产环境如果业务对数据库性能要求非常高,建议搭配适量的​​NVMe​​​协议的​​SSD​​盘。


Linux操作系统


内核参数设置

Linux的内核参数在​​/etc/sysctl.conf​​里修改。通常数据库软件的原理都会内部使用多线程,使用信号量,并且大量读写文件和网络设备(本质上也是文件)。所以ORACLE数据库的安装里会建议调整相关内核参数,OceanBase也是如此。这些参数都是共性。

​vi /etc/sysctl.conf​​​​# for database​​​​ net.core.somaxconn = 2048​​​​ net.core.netdev_max_backlog = 10000​​​​ net.core.rmem_default = 16777216​​​​ net.core.wmem_default = 16777216​​​​ net.core.rmem_max = 16777216​​​​ net.core.wmem_max = 16777216​​​​ net.ipv4.ip_local_port_range = 3500 65535​​​​ net.ipv4.ip_forward = 0​​​​ net.ipv4.conf.default.rp_filter = 1​​​​ net.ipv4.conf.default.accept_source_route = 0​​​​ net.ipv4.tcp_syncookies = 0​​​​ net.ipv4.tcp_rmem = 4096 87380 16777216​​​​ net.ipv4.tcp_wmem = 4096 65536 16777216​​​​ net.ipv4.tcp_max_syn_backlog = 16384​​​​ net.ipv4.tcp_fin_timeout = 15​​​​ net.ipv4.tcp_max_syn_backlog = 16384​​​​ net.ipv4.tcp_tw_reuse = 1​​​​ net.ipv4.tcp_tw_recycle = 1​​​​ net.ipv4.tcp_slow_start_after_idle=0​​​​ vm.swappiness = 0​​​​ kernel.core_pattern = /data/1/core-%e-%p-%t​​​​ vm.min_free_kbytes = 2097152​

生效命令

​sysctl -p​


Shell资源限制设置

数据库软件启动时也是在某个​​Shell​​会话下,而Linux默认会限制一个会话打开的资源。如文件句柄数、栈大小等等。这些默认值并不满足数据库软件的需求。也需要修改。

vi /etc/security/limits.conf​​​​* soft nofile 655350​​​​* hard nofile 655350​​​​* soft stack 20480​​​​* hard stack 20480​​​​* soft nproc 655360​​​​* hard nproc 655360​​​​* soft core unlimited​​​​* hard core unlimited​

修改完后要退出当前会话再次登录验证

​admin$ulimit -a​​​$ulimit -a​​​​core file size (blocks, -c) unlimited​​​​data seg size (kbytes, -d) unlimited​​​​scheduling priority (-e) 0​​​file size (blocks, -f) unlimited​​​​pending signals (-i) 385847​​​​max locked memory (kbytes, -l) 64​​​​max memory size (kbytes, -m) unlimited​​​open files (-n) 655360​​​​pipe size (512 bytes, -p) 8​​​​POSIX message queues (bytes, -q) 819200​​​​real-time priority (-r) 0​​​​stack size (kbytes, -s) 20480​​​​cpu time (seconds, -t) unlimited​​​​max user processes (-u) 655360​​​​virtual memory (kbytes, -v) unlimited​​​file locks (-x) unlimited​

安全和防火墙设定

SELinux是Linux的一个安全子系统,默认设置对进程访问权限限制很多。想用好SELinux非常麻烦,数据库软件通常都建议直接关闭这个服务。

在线关闭(其实是设置为Permissive)

#命令行下关闭​​#setenforce 0​​#getenforce​​​Permissive​​​

永久关闭,修改配置文件,并重启。

vi /etc/selinux/config​​​​SELINUX=disabled​

注意这个文件千万不要改错,否则重启后OS会启动失败。需要进入单用户模式修复。

Linux默认安装会启动防火墙,而数据库通常都会有一些监听端口响应用户请求。分布式数据库节点之间也会有通信需求。需要开通相关端口的访问权限。不过大企业运维里,一一去设置服务器的防火墙非常麻烦,一旦设置错误排查定位也不容易,所以都选择直接关闭。服务器的访问安全通过网络在​​VLAN​​级别设置端口访问的白名单和黑名单来保证。

#清理防火墙规则​​#iptables -F​​#查看防火墙规则​​#iptables -nvL​​#停用防火墙服务​​#systemctl stop filrewalld​​#禁用防火墙服务(防止重启后启动)​​#systemctl disable firewalld

时间同步

数据库服务器的时间和应用服务器的时间,以及用户生活中的时间应保持同步。企业生产环境都有专用的时间同步服务器(又叫​​NTP​​​服务器)。运维需要能排查服务器跟​​NTP​​源的时间差异。

​#配置ntp源​​​​vi /etc/ntp.conf​​​​#添加​​​​server 110.75.186.247 iburst minpoll 8 maxpoll 10​​​​#查看同步误差​​​​#ntpq -4p​​​
​​​#查看当前同步进度​​​​$ntpstat​​​​synchronised to NTP server (100.***.3.1) at stratum 3​​​​ time correct to within 6 ms​​​​ polling server every 64 s​

不过对于集群数据库而言,还要看节点之间的时间同步误差。理论上大家都跟​​NTP​​保持同步的话,各个节点之间的时间误差未必很大。

$clockdiff 100.***.152.81​​​.​​​host=100.***.152.81 rtt=750(187)ms/0ms delta=0ms/0ms Sat Jul 6 10:08:25 2019​

在很多企业的线下环境里,都没有专用的​​NTP​​​服务器,当需要时间同步时,可以挑选一台性能相对好的服务器做​​NTP​​服务器

​# yum -y install ntpd​​​​# vi /etc/ntp.conf​​​​#删除所有行​​​​#注释restrict default ignore​​​
​​​server 127.127.1.0 # local clock​​​​fudge 127.127.1.0 stratum 10 # 跟本地硬件同步​​​
​​​#当然,我们也可以添加server xxx.xxx.xxx.xxx,让他和其他的time server时间同步。​

各个机器配置​​server​​后地址为​​NTP​​源即可。第一次如果通过​​clockdiff​​发现跟​​NTP​​源时间差异很大,可以先用 

​ntpdate -u NTP源IP​​ 强制同步时间。注意手动同步可能跟自动同步会有冲突:​​1 Sep 20:09:19 ntpdate[2614]: the NTP socket is in use, exiting​​。这个避开同时运行即可。

然后重启 ntpd服务

#systemctl restart ntpd

​NTP​​​同步有个特点,一旦时间相差很大时,同步的时候会一点点缩小差距,目地是为了避免时间跳动范围太大。对于OceanBase集群数据库而言,各个节点的时间误差必须保证在​​100ms​​​以内(否则集群的核心选举服务会异常),​​50ms​​​以内比较保险,​​10ms​​​以内最佳。如果​​NTP​​​自动同步服务依然不能保证各个节点时间误差在要求以内,那可以用​​crontab​​每分钟定时同步。快速恢复集群的稳定性比什么都重要。

#crontab -e​​​* * * * * /sbin/ntpdate -u 100.***.152.81 >> /tmp/ntpdate.log 2>&1​​​

用户设置

新建用户是最简单的操作,用​​useradd​​​命令即可。不过很少有人会指定用户的​​uid​​​和​​gid​​​。这里就提一下,可能在某些情况下涉及到目录的共享时,虽然都是同一个用户但是由于各自的​​uid​​​以及​​gid​​不同导致有权限问题。

# groupadd -g 500 admin​​# useradd -u 500 -g 500 admin​​
​​# groupmod -g 500 admin​​# usermod -u 500 -g 500 admin

文件系统设置

所有的关系型数据库都有事务日志(通常说的​​Redo​​​),日志的写​​IO​​​特点是顺序​​IO​​​,数据文件的写​​IO​​​特点多是随机​​IO​​。为了性能考虑,最佳实践通常都是建议存放数据文件和事务日志文件的设备文件彼此独立,这样减少彼此的争用。通常性能最好的磁盘会存放事务日志(日志写可能是数据库性能的瓶颈)。

这里有很多种做法。

如果机器盘很多,那么建议2块盘做​​RAID 1​​​给OS用,其他的盘分为两部分,分别做​​RAID 10​​​或​​RAID 5​​,输出两块物理设备,然后分别格式化为文件系统。

如果机器盘不多时,分开可能难以兼顾OS、数据和日志的空间或性能需求。则可以用​​LVM​​​将多块盘(​​PV​​​)聚合在一起,然后划分出不同的逻辑设备(​​LV​​),然后再针对性格式化为文件系统,提供给数据和日志使用。

LVM是卷管理软件,对管理磁盘非常方便,将物理层和业务层彻底隔离,可以很方便给LV扩容和缩容(而fdisk分区软件则有扩容不方便问题)。Linux在默认安装的时候,常用LVM管理磁盘。运维需要详细看看分区内容是否合理。特别是作为数据库服务器,手动使用​​LVM​​管理极为重要,一定要尽可能的保证数据目录和日志目录使用的设备尽可能的独立。

还有一种情形,服务器只有两块盘,这个时候还要做​​RAID​​最后只能输出一块设备。这时候不管怎么管理划分,在底层数据文件和日志文件都是共用一个物理设备。除非这个盘是NVME协议的SSD大盘,否则实际性能并不很好。这样的服务器,也并不适合做数据库服务器用。

总结: 以上要求可以作为数据库主机的通用安装模板.

Docker技术


以前安装数据库都是DBA手动一步一步安装,数据库厂商也写了很详尽的安装文档,在安装的过程中学习。当大量数据库使用普通服务器时(指的是MySQL),DBA一台台手动安装可能就比较麻烦,还容易出错。除了操作系统安装自动化配置安装模板外,还有就是用Docker部署。

对于要安装的应用或数据库,首先制作一个docker镜像,将基本的配置、软件包都包含进去,然后写编排任务,在启动docker以后动态的根据配置传递不同的启动参数和执行一些固定的自定义初始化操作。Docker需要掌握一些基本的命令。

首先建议给docker准备一个专用的文件系统用于存放镜像文件,目录名:​​/docker​​。

其次就是安装docker

# 安装docker软件​​# yum -y install docker​​#启动docker服务​​# systemctl start docker

然后就是加载镜像、查看和运维docker。

# 加载镜像​​# docker load -i ocp2.tar.gz​​# 查看镜像​​# docker images​​# 查看运行的docker​​# docker ps​​# 查看所有的docker(包括已停止的)​​# docker ps -a​​# 启动/停止/重启 某个 docker​​# docker start/stop/restart xxxxx(docker标识或名称)​​# 删除 docker​​# docker rm xxx​​# 删除镜像​​# docker rmi xxx​​# 查看docker运行日志​​# docker logs xxx​​# 进入docker​​# docker exec -it xxxxx(docker标识或名称) bash​​# 向docker复制文件​​# docker cp filexxx.gz xxxx:~/ # xxxx是docker标识或名称​​

OceanBase的安装支持手动安装方式和自动安装,自动安装是通过OCP平台做的。OCP的安装是使用Antman产品(原理是Docker)部署,要求有三台物理机。会在每台机器上起3个Docker,分别是OCPOBProxyOB。这个OBOCP的元数据库,是运维最重要的数据库,所以建议机器配置不要低于业务数据库主机要求。

运维问题定位


如果问题有明确的报错信息,则根据报错信息定位。

比如说报不能打开文件之类,实际上有成功的也有失败的,则看用户的​​ulimit​​​设置里参数是否合理。如果是没有权限打开文件,则看文件所在目录的owner,进程​​owner​​​是否正确。如果问题是进程异常退出,则看系统日志​​/var/log/messages​​里是否有OOM之类报错。

如果OB数据库基本的SQL都报超时错误,则先看OB集群的多个节点之前的时间是否同步,NTP服务器是否正常等。

性能问题

有时候主机会表现出性能下降,进而导致数据库出现异常。二者之间的联系并不一定表现的很直接。因此在碰到问题的时候,可以顺便快速的看看主机的性能是否正常。通常只需要看CPU、内存、磁盘、网络就行。这里直接推荐用一个命令(​​tsar​​)就可以看所有的。

  • CPU性能

CPU用​​top​​​命令也可以看。原理相同。通常情况下,数据库很忙的时候,​​load​​​会偏高、​​user​​​利用率会相对比较高。再从​​top​​​命令里看是哪个进程。如果是数据库进程,那基本确认是数据库内部性能问题。如果​​sys​​​利用率也相对比较高(如超过​​20​​​),则留意OS的异常。如果​​wait​​​利用率相对比较高,则看看​​IO​​的性能。

​load​​​的结果里​​load1​​​,​​load5​​​,​​load15​​​分别代表1分钟内,5分钟内,15分钟内平均值。可以看出​​load​​变化趋势。

$tsar --cpu --load -l -i 3​​​​Time -----------------------cpu---------------------- -------------------load-----------------​​​​Time user sys wait hirq sirq util load1 load5 load15 runq plit​​​​07/07/19-15:24:54 25.59 10.62 3.08 0.00 0.42 36.63 13.78 12.99 12.15 5.00 2.8K​​​​07/07/19-15:24:57 25.42 10.63 7.10 0.00 0.42 36.46 13.72 12.99 12.15 10.00 2.8K​​​​07/07/19-15:25:00 25.25 10.11 3.85 0.00 0.40 35.77 13.58 12.97 12.15 3.00 2.8K​​​​07/07/19-15:25:03 29.34 11.31 4.89 0.00 0.48 41.13 13.58 12.97 12.15 7.00 2.8K​​​​07/07/19-15:25:06 24.80 9.93 5.92 0.00 0.36 35.09 13.37 12.94 12.14 25.00 2.8K​​​​^C​​​

  • MEM性能

Memory主要是关注​​free​​​、​​buffer​​​、​​cache​​的变化是否正常。通常运行一段时间后数据库主机的内存分布就比较固定了。如有异常变化,还需要结合其他信息判断。

​#tsar --mem -l -i 3​​​​Time -----------------------mem----------------------​​​​Time free used buff cach total util​​​​07/07/19-15:31:46 3.0G 31.2G 1.8G 58.2G 94.2G 33.16​​​​07/07/19-15:31:49 3.0G 31.2G 1.8G 58.2G 94.2G 33.13​​​​07/07/19-15:31:52 3.0G 31.2G 1.8G 58.2G 94.2G 33.15​​​​07/07/19-15:31:55 3.0G 31.2G 1.8G 58.2G 94.2G 33.15​​​​^C​

  • IO性能

看IO性能首先要确认当前的磁盘分区、文件系统设置等。通过​​fdisk​​​、​​mount​​​和​​df -h​​​命令查看。找到数据库数据和文件所在的磁盘,使用​​tsar​​​观察​​IO​​性能。对于一个磁盘的吞吐能力,响应时间水平应该事先有所了解。

#ll /dev/mapper/ob_vg-ob_data​​​lrwxrwxrwx 1 root root 7 Jun 12 15:28 /dev/mapper/ob_vg-ob_data -> ../dm-1​​​
​​#ll /dev/mapper/ob_vg-ob_log​​​lrwxrwxrwx 1 root root 7 Jun 12 15:28 /dev/mapper/ob_vg-ob_log -> ../dm-0​​​
​​#tsar --io -I dm-0 -l -i 3​​​Time ------------------------------------------dm-0------------------------------------------​​​​Time rrqms wrqms rs ws rsecs wsecs rqsize qusize await svctm util​​​​07/07/19-15:38:09 0.00 0.00 0.00 251.67 0.00 5.3K 21.67 2.00 8.89 3.97 99.87​​​​07/07/19-15:38:12 0.00 0.00 0.00 231.67 0.00 4.7K 20.85 2.00 9.08 3.95 91.50​​​​07/07/19-15:38:15 0.00 0.00 0.00 227.33 0.00 1.7K 7.73 1.00 8.71 4.39 99.73​​​​07/07/19-15:38:18 0.00 0.00 0.00 213.33 0.00 1.3K 6.36 1.00 8.31 4.31 92.00​​​​07/07/19-15:38:21 0.00 0.00 0.00 202.33 0.00 1.1K 5.54 1.00 9.09 4.51 91.20​​​​07/07/19-15:38:24 0.00 0.00 0.00 230.67 0.00 1.3K 5.57 1.00 8.34 4.32 99.73​​​​07/07/19-15:38:27 0.00 0.00 0.00 203.33 0.00 1.1K 5.65 1.00 8.65 4.49 91.27​​​​07/07/19-15:38:30 0.00 0.00 0.00 224.67 0.00 1.5K 6.84 1.00 8.34 4.43 99.47​​​​07/07/19-15:38:33 0.00 0.00 0.00 232.33 0.00 3.0K 13.11 2.00 8.61 3.96 92.07​​​​07/07/19-15:38:36 0.00 0.00 0.00 210.67 0.00 1.2K 5.80 1.00 8.27 4.36 91.87​​​​07/07/19-15:38:39 0.00 0.00 0.00 227.33 0.00 1.3K 5.75 1.00 8.16 4.39 99.90​​​​^C​

其中​​IO Util​​​是个比较复杂的参数。如果是机械盘,这个​​Util​​​可以反映出磁盘的繁忙程度,​​svctm​​​会在几毫秒以上。如果是​​SSD​​​盘,​​svctm​​​会在零点几毫秒。关于利用率有个近似公式:​​利用率U = 吞吐量 * 每次平均服务时间​​​. 所以SSD盘需要看响应时间(​​svctm​​​)、等待时间(​​await​​)等信息综合判断是否到瓶颈。

  • 网络

首先通过ethtool命令查看网卡的速度。然后通过tsar命令看网卡实际上传下载速度以及丢包率。如果接近或者超过网卡的能力,则表示网卡此刻接近吞吐量瓶颈。

#ethtool  bond0
Settings for bond0:
Supported ports: [ ]
Supported link modes: Not reported
Supported pause frame use: No
Supports auto-negotiation: No
Advertised link modes: Not reported
Advertised pause frame use: No
Advertised auto-negotiation: No
Speed: 2000Mb/s
Duplex: Full
Port: Other
PHYAD: 0
Transceiver: internal
Auto-negotiation: off
Link detected: yes

#tsar --traffic -l -i 3
Time ---------------------traffic--------------------
Time bytin bytout pktin pktout pkterr pktdrp
07/07/19-15:58:24 8.7M 2.3M 9.9K 6.1K 0.00 0.00
07/07/19-15:58:27 9.0M 2.6M 10.0K 6.2K 0.00 0.00
07/07/19-15:58:30 9.7M 2.7M 10.7K 6.5K 0.00 0.00
07/07/19-15:58:33 10.7M 2.6M 11.0K 6.1K 0.00 0.00
07/07/19-15:58:36 8.5M 2.2M 9.5K 5.7K 0.00 0.00
^C



备注:

主机的性能是最容易看最基础的,如果主机在某方面呈现性能瓶颈,数据库的性能和稳定性很可能会受影响。二者之间的联系并不会表现的很直接,需要多观察总结成经验。tsar 更多用法参见《推荐一款淘宝开源的主机性能采集软件——tsar》。


总结


以上大部分说的是用普通服务器作为数据库服务器的一些运维经验。传统业务转型到分布式数据库架构后,普通服务器的规模和运维工作量会增加,因此一些基础的数据库主机安装模板、运维规范以及自动化运维都会应运而生。然而自动化运维产品不是智能化产品,当环境不标准或者异常时,其机制就可能失效,就需要运维介入处理。掌握一些基础的技能是数据库运维安全驾驶的前提。