mysql“write”命令列表,或者如何确定mysql命令是否涉及写入操作

nbysray5  于 2021-06-18  发布在  Mysql
关注(0)|答案(2)|浏览(327)

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

slwdgvem

slwdgvem1#

好吧,在这个问题上你问了很多,所以你能做的是:
如果您想要mysql执行的操作的全局计数器,那么
显示状态
将返回服务器的所有计数器,包括用于以下操作的计数器

Com_insert 
Com_insert_select 
Com_replace
Com_replace_select
Com_select 
Com_update

您只需检查这些值是否执行了任何此类操作
监视插入、更新、替换等的另一种方法是使用触发器(https://dev.mysql.com/doc/refman/8.0/en/trigger-syntax.html). 文档中的示例清楚地显示了触发器在哪里发挥了最大的作用—作为增加本地计数器(变量)的手段。但您仍然应该记住,触发器是特定于当前操作/表的。
说到边缘案件。是的,比如交易和程序。程序可以包含上面的许多操作。所以你需要检查一下。
一般来说,从db外部监视insert这样的原子操作并不是最好的主意。您应该依赖db means(触发器、变量、全局计数器)

tjvv9vkg

tjvv9vkg2#

我在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();
    }

}

相关问题