Mysql列表";写下;命令,或者如何确定mysql命令是否涉及写入操作

Mysql列表";写下;命令,或者如何确定mysql命令是否涉及写入操作,mysql,Mysql,我希望识别mysql数据库的所有写入命令,并在每次调用mysql写入命令时执行一个函数。这可能类似于过滤(阻止)某些命令或在新线程上发出web请求。到目前为止,我计划使用mysql的常规日志来确定这些写命令是什么,但这不适用于过滤(阻塞)命令 下面是我发现的一些“写入”mysql命令的列表: 插入 更新 替换 我还有其他需要担心的边缘案例吗?例如,是否有任何东西可以修改select命令,使其以某种方式成为写入操作?下面的写操作最终会作为上述3种操作之一重新执行吗 “set”是对数据库的写入命

我希望识别mysql数据库的所有写入命令,并在每次调用mysql写入命令时执行一个函数。这可能类似于过滤(阻止)某些命令或在新线程上发出web请求。到目前为止,我计划使用mysql的常规日志来确定这些写命令是什么,但这不适用于过滤(阻塞)命令

下面是我发现的一些“写入”mysql命令的列表:

  • 插入
  • 更新
  • 替换
我还有其他需要担心的边缘案例吗?例如,是否有任何东西可以修改select命令,使其以某种方式成为写入操作?下面的写操作最终会作为上述3种操作之一重新执行吗


“set”是对数据库的写入命令,还是仅针对mysql会话中使用的变量?

好吧,在这个问题上,您已经问了很多,那么您可以做什么:

  • 如果您需要MySQL执行的操作的全局计数器,那么

    显示状态

  • 将返回服务器的所有计数器,包括用于以下操作的计数器

    Com_insert 
    Com_insert_select 
    Com_replace
    Com_replace_select
    Com_select 
    Com_update
    
    您只需检查这些值是否执行了任何此类操作

  • 监视插入、更新、替换等的另一种方法是使用触发器()。文档中的示例清楚地显示了触发器在哪里发挥了最大的作用——作为增加本地计数器(变量)的手段。但您仍然应该记住,触发器是特定于当前操作/表的

  • 说到边缘案例。是的,例如交易和程序。该过程可以包括上述许多操作。因此,您需要检查这些

  • 一般来说,从数据库外部监视像INSERT这样的原子操作并不是最好的主意。您应该依赖于DB means(触发器、变量、全局计数器)


  • 我在PHP代码中做过类似的过滤。但背景不同;我们使用的是主从复制体系结构。为了将查询定向到相关服务器(将查询读取到从属服务器,将查询写入主服务器),编写了一个自定义函数来标识查询的类型

    值得注意的一点是,事务/锁定/解锁操作中的查询始终被视为写查询

    此外,对于
    Set
    ,只有
    Set AUTOCOMMIT
    Set TRANSACTION
    是写入命令

    请在下面找到我们正在使用的实际代码的大致精简版本:

    /*
    * All the WRITE operation commands
    */
    $write_commands = array(
        'create', 
        'alter', 
        'drop', 
        'truncate',
        'comment', 
        'rename', 
        'insert', 
        'update',
        'delete', 
        'merge', 
        'call', 
        'lock', 
        'unlock',
        'start', 
        'commit', 
        'rollback', 
        'savepoint',
        'set', 
        'replace' 
    );
    
    
    /*
    * method to determine whether Read or Write
    * @param $sql String (SQL query string)
    * @return: void
    */
    function determineReadOrWrite(string $sql): void {
    
        $dml_query = false;
    
        $words = str_word_count(strtolower(trim($sql)), 1);
        $first_word = isset($words[0]) ? $words[0] : '';
        $second_word = isset($words[1]) ? $words[1] : '';
    
        if (in_array($first_word, $this->write_commands)) {
            /* if it is not "set" then we set to master link */
            if ($first_word !== 'set'
            || ($first_word === 'set' && $second_word === 'autocommit')
            || ($first_word === 'set' && $second_word === 'transaction')
            ) {
                $dml_query = true;
    
                /* If we Lock tables or Begin a Transaction, we should run on Write servers only */
                /* till we Commit/Rollback or Unlock Tables */
                if(($first_word === 'start' && $second_word === 'transaction') 
                || $first_word === 'lock'){
    
                    /* Set whether the current query is starting a Transaction / Lock etc */
                    $this->wait_for_commit_rollback = true;
                }
    
                /* We are doing Commit/Rollback or Unlock Tables */
                if ($first_word === 'commit' 
                || $first_word === 'rollback' 
                || $first_word === 'unlock') {
                    $this->wait_for_commit_rollback = false;
                }
            }
        }
    
        /* It's a insert/update/delete/etc query - to be run on Write Db only */
        if ($dml_query || $this->wait_for_commit_rollback) { 
            $this->setActiveConnectionToWrite(true);            
    
        } else {
            $this->setActiveConnectionToRead();
        }
    
    }
    

    是否要在应用程序代码中执行此筛选?是PHP吗?我认为在mysql级别上修改会更容易,但如果不可能,那么在该级别上修改会更好。它是php/laravelOk。我已经编写了一个自定义代码来实现类似的功能,但用于不同的需求—主从负载分布。我很快就会发布一个答案。