찾다
데이터 베이스MySQL 튜토리얼将Hadoop RPC框架应用于多节点任务调度

在hadoop中,主从节点之间保持着心跳通信,用于传输节点状态信息、任务调度信息以及节点动作信息等等。 hdfs的namenode与datanode,mapreduce的jobtracker与tasktracker,hbase的hmaster与 regionserver之间的通信,都是基于hadoop RPC。Hadoop RPC是hadoop

在hadoop中,主从节点之间保持着心跳通信,用于传输节点状态信息、任务调度信息以及节点动作信息等等。 hdfs的namenode与datanode,mapreduce的jobtracker与tasktracker,hbase的hmaster与 regionserver之间的通信,都是基于hadoop RPC。Hadoop RPC是hadoop里非常基础的通信框架。hadoop 2.0以前hadoop RPC的数据序列化是通过实现自己定义的Writable接口实现,而从hadoop 2.0开始,数据的序列化工作交给了ProtocolBuffer去做。关于Hadoop RPC的实现原理已经有很多文章进行了详细的介绍(源码级强力分析hadoop的RPC机制,Hadoop基于Protocol Buffer的RPC实现代码分析-Server端,带有HA功能的Hadoop Client端RPC实现原理与代码分析),这里就不在赘述了。下面就直接引入问题和方案吧。

问题

工作中经常需要在定时任务系统上写一些定时任务,随着业务规模的增长和扩大,需要定时处理的任务越来越多,任务之间的执行间隔越来越小,某一时间段内(比如0点、整点或半点)执行的任务会越来越密集,只在一台机器上执行这些任务的话,会出现较大的风险:

  • 任务并发度较高时,单机的系统资源将成为瓶颈
  • 如果一个任务的运行占用了整个机器的大部分资源,比如sql查询耗费巨大内存和CPU资源,将直接影响其他任务的运行
  • 任务失败后,如果仍然在同一台节点自动重新执行,失败率较高
  • 机器宕机后,必须第一时间重启机器或重新部署定时任务系统,所有任务都不能按时执行
  • 等等

方案

可想而知的是,可以通过将定时任务系统进行分布式改造,使用多个节点执行任务,将任务分发到不同节点上进行处理,并且完善失败重试机制,从而提高系统稳定性,实现任务系统的高可靠。

既然是在多个节点之间分发任务,肯定得有个任务的管理者(主节点),在我们现有的系统中,也就是一套可以部署定时任务的web系统,任务代码更新后,部署好这套web系统,即可通过web页面设置定时任务并且进行调度(在单个节点上执行)。执行任务的节点(子节点)有多个以后,如何分发任务到子节点呢,我们可以把任务的信息封装成一个bean,通过RPC发布给子节点,子节点通过这个任务bean获得任务信息,并在指定的时刻执行任务。同时,子节点可以通过与主节点的心跳通信将节点状态和执行任务的情况告诉主节点。这样其实就与hadoop mapreduce分发任务有点相似了,呵呵,这里主节点与子节点之间的通信,我们就可以通过Hadoop RPC框架来实现了,不同的是,我们分发的任务是定时任务,发布任务时需要将任务的定时信息一并发给子节点。

实现

单点的定时任务系统是基于Quartz的,在分布式环境下,可以继续基于Quartz进行改造,任务的定时信息可以通过Quartz中的JobDetail和Trigger对象来描述并封装,加上任务执行的入口类信息,再通过RPC由主节点发给子节点。子节点收到封装好的任务信息对象后,再构造JobDetail和Trigger,设置好启动时间后,通过入口类启动任务。下面是一个简单的demo。

以下是一个简单的定时任务信息描述对象CronJobInfo,包括JobDetailInfo和TriggerInfo两个属性:

/**
* 定时任务信息,包括任务信息和触发器信息
*/
public class CronJobInfo implements Writable
{
    private JobDetailInfo jobDetailInfo = new JobDetailInfo();
    private TriggerInfo triggerInfo = new TriggerInfo();
    @Override
    public void readFields(DataInput in) throws IOException
    {
        jobDetailInfo.readFields(in);
        triggerInfo.readFields(in);
    }
    @Override
    public void write(DataOutput out) throws IOException
    {
        jobDetailInfo.write(out);
        triggerInfo.write(out);
    }
    // getters and setters...
}

任务信息JobDetailInfo,由主节点构造,子节点解析构造JobDetail对象:

public class JobDetailInfo implements Writable
{
    private String name; // 任务名称
    private String group = Scheduler.DEFAULT_GROUP; // 任务组
    private String description; // 任务描述
    private Class jobClass; // 任务的启动类
    private JobDataMap jobDataMap; // 任务所需的参数,用来给作业提供数据支持的数据结构
    private boolean volatility = false; // 重启应用之后是否删除任务的相关信息,
    private boolean durability = false; // 任务完成之后是否依然保留到数据库
    private boolean shouldRecover = false; // 应用重启之后时候忽略过期任务
    @Override
    public void readFields(DataInput in) throws IOException
    {
        name = WritableUtils.readString(in);
        group = WritableUtils.readString(in);
        description = WritableUtils.readString(in);
        String className = WritableUtils.readString(in);
        if (className != null)
        {
          try
          {
             jobClass = Class.forName(new String(className));
          }
          catch (ClassNotFoundException e)
          {
             e.printStackTrace();
          }
        }
        int dataMapSize = WritableUtils.readVInt(in);
        while (dataMapSize-- > 0)
        {
           String key = WritableUtils.readString(in);
           String value = WritableUtils.readString(in);
           jobDataMap.put(key, value);
        }
        volatility = in.readBoolean();
        durability = in.readBoolean();
        shouldRecover = in.readBoolean();
    }
    @Override
    public void write(DataOutput out) throws IOException
    {
        WritableUtils.writeString(out, name);
        WritableUtils.writeString(out, group);
        WritableUtils.writeString(out, description);
        WritableUtils.writeString(out, jobClass.getName());
        if (jobDataMap == null)
            WritableUtils.writeVInt(out, 0);
        else
        {
            WritableUtils.writeVInt(out, jobDataMap.size());
            for (Object k : jobDataMap.keySet())
            {
                WritableUtils.writeString(out, k.toString());
                WritableUtils.writeString(out, jobDataMap.get(k).toString());
            }
        }
        out.writeBoolean(volatility);
        out.writeBoolean(durability);
        out.writeBoolean(shouldRecover);
   }
   //getters and setters
   //.....
}

任务触发器信息TriggerInfo ,由主节点构造,子节点解析构造Trigger对象:

public class TriggerInfo implements Writable
{
    private String name; // trigger名称
    private String group = Scheduler.DEFAULT_GROUP; // triger组名称
    private String description; // trigger描述
    private Date startTime; // 启动时间
    private Date endTime; // 结束时间
    private long repeatInterval; // 重试时间间隔
    private int repeatCount; //重试次数
    @Override
    public void readFields(DataInput in) throws IOException
    {
       name = WritableUtils.readString(in);
       group = WritableUtils.readString(in);
       description = WritableUtils.readString(in);
       long start = in.readLong();
       startTime = start==0 ? null : new Date(start);
       long end = in.readLong();
       endTime = end==0 ? null : new Date(end);
       repeatInterval = in.readLong();
       repeatCount = in.readInt();
    }
    @Override
    public void write(DataOutput out) throws IOException
    {
       WritableUtils.writeString(out, name);
       WritableUtils.writeString(out, group);
       WritableUtils.writeString(out, description);
       out.writeLong(startTime == null ? 0 : startTime.getTime());
       out.writeLong(endTime == null ? 0 : endTime.getTime());
       out.writeLong(repeatInterval);
       out.writeInt(repeatCount);
    }
    //getters and setters
    //.....
}

主从节点通信的协议:

public interface TaskProtocol extends VersionedProtocol
{
	public CronJobInfo hearbeat();
}

在这个demo中,主节点启动后,启动RPC server线程,等待客户端(子节点)的连接,当客户端调用heartbeat方法时,主节点将会生成一个任务信息返回给客户端:

public class TaskScheduler implements TaskProtocol
{
	private Logger logger = Logger.getLogger(getClass());
	private Server server;
	public TaskScheduler()
	{
		try
		{
			server = RPC.getServer(this, "192.168.1.101", 8888, new Configuration());
			server.start();
			server.join();
		}
		catch (UnknownHostException e)
		{
			e.printStackTrace();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		catch (InterruptedException e)
		{
			e.printStackTrace();
		}
	}
	@Override
	public long getProtocolVersion(String arg0, long arg1) throws IOException
	{
		return 1;
	}
	@Override
	public CronJobInfo generateCronJob()
	{
		// 1、创建JobDetial对象
		JobDetailInfo detail = new JobDetailInfo();
		// 设置工作项
		detail.setJobClass(DemoTask.class);
		detail.setName("MyJob_1");
		detail.setGroup("JobGroup_1");
		// 2、创建Trigger对象
		TriggerInfo trigger = new TriggerInfo();
		trigger.setName("Trigger_1");
		trigger.setGroup("Trigger_Group_1");
		trigger.setStartTime(new Date());
		// 设置重复停止时间,并销毁该Trigger对象
		Calendar c = Calendar.getInstance();
		c.setTimeInMillis(System.currentTimeMillis() + 1000 * 1L);
		trigger.setEndTime(c.getTime());
		// 设置重复间隔时间
		trigger.setRepeatInterval(1000 * 1L);
		// 设置重复执行次数
		trigger.setRepeatCount(3);
		CronJobInfo info = new CronJobInfo();
		info.setJobDetailInfo(detail);
		info.setTriggerInfo(trigger);
		return info;
	}
	public static void main(String[] args)
	{
		TaskScheduler ts = new TaskScheduler();
	}
}

demo任务类,打印信息:

public class DemoTask implements Job
{
	public void execute(JobExecutionContext context)
			throws JobExecutionException
	{
		System.out.println(this + ": executing task @" + new Date());
	}
}

子节点demo,启动后连接主节点,远程调用generateCronJob方法,获得一个任务描述信息,并启动定时任务

public class TaskRunner
{
	private Logger logger = Logger.getLogger(getClass());
	private TaskProtocol proxy;
	public TaskRunner()
	{
		InetSocketAddress addr = new InetSocketAddress("localhost", 8888);
		try
		{
			proxy = (TaskProtocol) RPC.waitForProxy(TaskProtocol.class, 1, addr,
					new Configuration());
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}
	public void close()
	{
		RPC.stopProxy(proxy);
	}
	/**
	 * 从server获取一个定时任务
	 */
	public void getCronJob()
	{
		CronJobInfo info = proxy.generateCronJob();
		JobDetail jobDetail = getJobDetail(info.getJobDetailInfo());
		SimpleTrigger trigger = getTrigger(info.getTriggerInfo());
		// 创建Scheduler对象,并配置JobDetail和Trigger对象
		SchedulerFactory sf = new StdSchedulerFactory();
		Scheduler scheduler = null;
		try
		{
			scheduler = sf.getScheduler();
			scheduler.scheduleJob(jobDetail, trigger);
			// 执行启动操作
			scheduler.start();
		}
		catch (SchedulerException e)
		{
			e.printStackTrace();
		}
	}
	/**
	 * @param jobDetailInfo
	 * @return
	 */
	private JobDetail getJobDetail(JobDetailInfo info)
	{
		JobDetail detail = new JobDetail();
		detail.setName(info.getName());
		detail.setGroup(info.getGroup());
		detail.setDescription(info.getDescription());
		detail.setJobClass(info.getJobClass());
		detail.setJobDataMap(info.getJobDataMap());
		detail.setRequestsRecovery(info.isShouldRecover());
		detail.setDurability(info.isDurability());
		detail.setVolatility(info.isVolatility());
		logger.info("client get jobdetail:" + detail);
		return detail;
	}
	/**
	 * @param triggerInfo
	 * @return
	 */
	private SimpleTrigger getTrigger(TriggerInfo info)
	{
		SimpleTrigger trigger = new SimpleTrigger();
		trigger.setName(info.getName());
		trigger.setGroup(info.getGroup());
		trigger.setDescription(info.getDescription());
		trigger.setStartTime(info.getStartTime());
		trigger.setEndTime(info.getEndTime());
		trigger.setRepeatInterval(info.getRepeatInterval());
		trigger.setRepeatCount(info.getRepeatCount());
		logger.info("client get trigger:" + trigger);
		return trigger;
	}
	public static void main(String[] args)
	{
		TaskRunner t = new TaskRunner();
		t.getCronJob();
		t.close();
	}
}

先启动TaskScheduler,再启动TaskRunner,结果如下:

  • TaskScheduler:

2013-01-20 15:42:21,661 [Socket Reader #1 for port 8888] INFO? [org.apache.hadoop.ipc.Server] – Starting Socket Reader #1 for port 8888
2013-01-20 15:42:21,662 [main] INFO? [org.apache.hadoop.ipc.metrics.RpcMetrics] – Initializing RPC Metrics with hostName=TaskScheduler, port=8888
2013-01-20 15:42:21,706 [main] INFO? [org.apache.hadoop.ipc.metrics.RpcDetailedMetrics] – Initializing RPC Metrics with hostName=TaskScheduler, port=8888
2013-01-20 15:42:21,710 [IPC Server listener on 8888] INFO? [org.apache.hadoop.ipc.Server] – IPC Server listener on 8888: starting
2013-01-20 15:42:21,711 [IPC Server Responder] INFO? [org.apache.hadoop.ipc.Server] – IPC Server Responder: starting
2013-01-20 15:42:21,711 [IPC Server handler 0 on 8888] INFO? [org.apache.hadoop.ipc.Server] – IPC Server handler 0 on 8888: starting
2013-01-20 15:42:24,084 [IPC Server handler 0 on 8888] INFO? [org.mh.rpc.task.TaskScheduler] – generate a task: org.mh.rpc.task.JobDetailInfo@1f26605

  • TaskRunner:

2013-01-20 15:42:26,323 [main] INFO? [org.mh.rpc.task.TaskRunner] – client get jobdetail:JobDetail ‘JobGroup_1.MyJob_1′:? jobClass: ‘org.mh.rpc.quartz.GetSumTask isStateful: false isVolatile: false isDurable: false requestsRecovers: false
2013-01-20 15:42:26,329 [main] INFO? [org.mh.rpc.task.TaskRunner] – client get trigger:Trigger ‘Trigger_Group_1.Trigger_1′:? triggerClass: ‘org.quartz.SimpleTrigger isVolatile: false calendar: ‘null’ misfireInstruction: 0 nextFireTime: null
2013-01-20 15:42:26,382 [main] INFO? [org.quartz.simpl.SimpleThreadPool] – Job execution threads will use class loader of thread: main
2013-01-20 15:42:26,411 [main] INFO? [org.quartz.core.SchedulerSignalerImpl] – Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
2013-01-20 15:42:26,411 [main] INFO? [org.quartz.core.QuartzScheduler] – Quartz Scheduler v.1.6.5 created.
2013-01-20 15:42:26,413 [main] INFO? [org.quartz.simpl.RAMJobStore] – RAMJobStore initialized.
2013-01-20 15:42:26,413 [main] INFO? [org.quartz.impl.StdSchedulerFactory] – Quartz scheduler ‘DefaultQuartzScheduler’ initialized from default resource file in Quartz package: ‘quartz.properties’
2013-01-20 15:42:26,413 [main] INFO? [org.quartz.impl.StdSchedulerFactory] – Quartz scheduler version: 1.6.5
2013-01-20 15:42:26,415 [main] INFO? [org.quartz.core.QuartzScheduler] – Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.
org.mh.rpc.quartz.DemoTask@1b66b06: executing task @Sun Jan 20 15:42:26 CST 2013

上面是一个简单的demo,演示了如何通过RPC将任务调度给节点去执行,对于Quartz来说,任务的形式可以千变万化,关键就看怎么去使用了,分发到多个节点上执行的话,就还需要对任务的信息做更多的封装了。

(本文已被阅读2次)

将Hadoop RPC框架应用于多节点任务调度 在hadoop中,主从节点之间保持着心跳通信,用于传输节点状态信息、任务调度信息以及节点动作信息等等。 hdfs的namenode与datanode,mapreduce的jobtracker与tasktracker,hbase的hmaster与 regionserver之间的通信,都是基于hadoop RPC。Hadoop RPC是hadoop里非常基础的通信框架。hadoop 2.0以前hadoop RPC的数据序列化是通过实现自己定义的Writable接口实现,而从hadoop 2.0开始,数据的序列化工作交给了ProtocolBuffer去做。关于Hadoop RPC的实现原理已经有很多文章进行了详细的介绍(源码级强力分析hadoop的RPC机制,Hadoop基于Protocol Buffer的RPC实现代码分析-Server端,带有HA功能的Hadoop Client端RPC实现原理与代码分析),这里就不在赘述了。下面就直接引入问题和方案吧。 问题 工作中经常需要在定时任务系统上写一些定时任务,随着业务规模的增长和扩大,需要定时处理的任务越来越多,任务之间的执行间隔越来越小,某一时间段内(比如0点、整点或半点)执行的任务会越来越密集,只在一台机器上执行这些任务的话,会出现较大的风险: 任务并发度较高时,单机的系统资源将成为瓶颈 如果一个任务的运行占用了整个机器的大部分资源,比如sql查询耗费巨大内存和CPU资源,将直接影响其他任务的运行 任务失败后,如果仍然在同一台节点自动重新执行,失败率较高 机器宕机后,必须第一时间重启机器或重新部署定时任务系统,所有任务都不能按时执行 等等 方案 可想而知的是,可以通过将定时任务系统进行分布式改造,使用多个节点执行任务,将任务分发到不同节点上进行处理,并且完善失败重试机制,从而提高系统稳定性,实现任务系统的高可靠。 既然是在多个节点之间分发任务,肯定得有个任务的管理者(主节点),在我们现有的系统中,也就是一套可以部署定时任务的web系统,任务代码更新后,部署好这套web系统,即可通过web页面设置定时任务并且进行调度(在单个节点上执行)。执行任务的节点(子节点)有多个以后,如何分发任务到子节点呢,我们可以把任务的信息封装成一个bean,通过RPC发布给子节点,子节点通过这个任务bean获得任务信息,并在指定的时刻执行任务。同时,子节点可以通过与主节点的心跳通信将节点状态和执行任务的情况告诉主节点。这样其实就与hadoop mapreduce分发任务有点相似了,呵呵,这里主节点与子节点之间的通信,我们就可以通过Hadoop RPC框架来实现了,不同的是,我们分发的任务是定时任务,发布任务时需要将任务的定时信息一并发给子节点。 实现 单点的定时任务系统是基于Quartz的,在分布式环境下,可以继续基于Quartz进行改造,任务的定时信息可以通过Quartz中的JobDetail和Trigger对象来描述并封装,加上任务执行的入口类信息,再通过RPC由主节点发给子节点。子节点收到封装好的任务信息对象后,再构造JobDetail和Trigger,设置好启动时间后,通过入口类启动任务。下面是一个简单的demo。 以下是一个简单的定时任务信息描述对象CronJobInfo,包括JobDetailInfo和TriggerInfo两个属性: 任务信息JobDetailInfo,由主节点构造,子节点解析构造JobDetail对象: 任务触发器信息TriggerInfo ,由主节点构造,子节点解析构造Trigger对象: 主从节点通信的协议: 在这个demo中,主节点启动后,启动RPC server线程,等待客户端(子节点)的连接,当客户端调用heartbeat方法时,主节点将会生成一个任务信息返回给客户端: demo任务类,打印信息: 子节点demo,启动后连接主节点,远程调用generateCronJob方法,获得一个任务描述信息,并启动定时任务 先启动TaskScheduler,再启动TaskRunner,结果如下: TaskScheduler: 2013-01-20 15:42:21,661 [Socket Reader #1 for port 8888] INFO? [org.apache.hadoop.ipc.Server] – Starting Socket Reader #1 for port 8888 2013-01-20 [...]将Hadoop RPC框架应用于多节点任务调度
성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
MySQL은 데이터 복제를 어떻게 처리합니까?MySQL은 데이터 복제를 어떻게 처리합니까?Apr 28, 2025 am 12:25 AM

MySQL은 비동기식, 반 동시성 및 그룹 복제의 세 가지 모드를 통해 데이터 복제를 처리합니다. 1) 비동기 복제 성능은 높지만 데이터가 손실 될 수 있습니다. 2) 반 동기화 복제는 데이터 보안을 향상 시키지만 대기 시간을 증가시킵니다. 3) 그룹 복제는 고 가용성 요구 사항에 적합한 다중 마스터 복제 및 장애 조치를 지원합니다.

설명 명세서를 사용하여 쿼리 성능을 분석 할 수있는 방법은 무엇입니까?설명 명세서를 사용하여 쿼리 성능을 분석 할 수있는 방법은 무엇입니까?Apr 28, 2025 am 12:24 AM

설명 설명은 SQL 쿼리 성능을 분석하고 개선하는 데 사용될 수 있습니다. 1. 쿼리 계획을 보려면 설명 명세서를 실행하십시오. 2. 출력 결과를 분석하고 액세스 유형, 인덱스 사용량 및 조인 순서에주의를 기울이십시오. 3. 분석 결과를 기반으로 인덱스 생성 또는 조정, 조인 작업을 최적화하며 전체 테이블 스캔을 피하여 쿼리 효율성을 향상시킵니다.

MySQL 데이터베이스를 어떻게 백업하고 복원합니까?MySQL 데이터베이스를 어떻게 백업하고 복원합니까?Apr 28, 2025 am 12:23 AM

논리 백업에 mysqldump를 사용하고 핫 백업을 위해 mysqlenterprisebackup을 사용하는 것은 mySQL 데이터베이스를 백업하는 효과적인 방법입니다. 1. MySQLDUMP를 사용하여 데이터베이스를 백업합니다 : MySQLDUMP-UROOT-PMYDATABASE> MYDATABASE_BACKUP.SQL. 2. Hot Backup : MySQLBackup- 사용자 = root-password = password-- backup-dir =/path/to/backupbackup에 mysqlenterprisebackup을 사용하십시오. 회복 할 때 해당 수명을 사용하십시오

MySQL에서 느린 쿼리의 일반적인 원인은 무엇입니까?MySQL에서 느린 쿼리의 일반적인 원인은 무엇입니까?Apr 28, 2025 am 12:18 AM

느린 MySQL 쿼리의 주된 이유는 인덱스의 누락 또는 부적절한 사용, 쿼리 복잡성, 과도한 데이터 볼륨 및 불충분 한 하드웨어 리소스가 포함됩니다. 최적화 제안에는 다음이 포함됩니다. 1. 적절한 인덱스 생성; 2. 쿼리 문을 최적화합니다. 3. 테이블 파티셔닝 기술 사용; 4. 적절하게 하드웨어를 업그레이드합니다.

MySQL의 견해는 무엇입니까?MySQL의 견해는 무엇입니까?Apr 28, 2025 am 12:04 AM

MySQL View는 SQL 쿼리 결과를 기반으로 한 가상 테이블이며 데이터를 저장하지 않습니다. 1) 뷰는 복잡한 쿼리를 단순화하고 2) 데이터 보안을 향상시키고 3) 데이터 일관성을 유지합니다. 뷰는 테이블처럼 사용할 수있는 데이터베이스에 저장된 쿼리이지만 데이터는 동적으로 생성됩니다.

MySQL과 다른 SQL 방언의 구문의 차이점은 무엇입니까?MySQL과 다른 SQL 방언의 구문의 차이점은 무엇입니까?Apr 27, 2025 am 12:26 AM

mysqldiffersfromothersqldialectsinsyntaxforlimit, 자동 점유, 문자열 comparison, 하위 쿼리 및 퍼포먼스 앤 알리 분석 .1) mysqluse Slimit, whilesqlSerVerusestOpandoracleSrownum.2) MySql'Sauto_incrementContrastSwithPostgresql'serialandoracle '

MySQL 파티셔닝이란 무엇입니까?MySQL 파티셔닝이란 무엇입니까?Apr 27, 2025 am 12:23 AM

MySQL 파티셔닝은 성능을 향상시키고 유지 보수를 단순화합니다. 1) 큰 테이블을 특정 기준 (예 : 날짜 범위)으로 작은 조각으로 나누고, 2) 데이터를 독립적 인 파일로 물리적으로 나눌 수 있습니다.

MySQL에서 어떻게 권한을 부여하고 취소합니까?MySQL에서 어떻게 권한을 부여하고 취소합니까?Apr 27, 2025 am 12:21 AM

MySQL에서 권한을 부여하고 취소하는 방법은 무엇입니까? 1. 보조금 명세서를 사용하여 grantallprivilegesondatabase_name.to'username'@'host '와 같은 부여 권한; 2. Revoke 문을 사용하여 Revokeallprivilegesondatabase_name.from'username'@'host '와 같은 권한을 취소하여 허가 변경의 적시에 의사 소통을 보장하십시오.

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

에디트플러스 중국어 크랙 버전

에디트플러스 중국어 크랙 버전

작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

Atom Editor Mac 버전 다운로드

Atom Editor Mac 버전 다운로드

가장 인기 있는 오픈 소스 편집기