Py学习  »  DATABASE

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

nick carraway • 6 年前 • 1501 次点击  

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

以下是我找到的一些“write”mysql命令的列表:

  • 插入
  • 更新
  • 代替

我还有其他需要担心的边缘问题吗?例如,是否有什么可以修改select命令以使其以某种方式成为写操作?以下写入操作最终会作为上述3种操作之一重新执行吗?

“set”是对数据库的写命令,还是只对MySQL会话中使用的变量?

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/38194
文章 [ 2 ]  |  最新文章 6 年前
Madhur Bhaiya
Reply   •   1 楼
Madhur Bhaiya    7 年前

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

}
Anton
Reply   •   2 楼
Anton    7 年前

嗯,你在这个问题上问了很多问题,所以你能做什么:

  1. 如果您想要mysql执行的操作的全局计数器,那么

    显示状态

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

Com_insert 
Com_insert_select 
Com_replace
Com_replace_select
Com_select 
Com_update

您只需检查这些值是否执行了任何此类操作

  1. 监视插入、更新、替换等的另一种方法是使用触发器( https://dev.mysql.com/doc/refman/8.0/en/trigger-syntax.html )文档中的示例清楚地显示了触发器在哪里做得最好——作为增加局部计数器(变量)的方法。但您仍然应该记住触发器是特定于当前操作/表的。

  2. 说到边缘案例。是的,例如交易和程序。程序可以包括上面的许多操作。所以你需要检查一下。

  3. 一般来说,从数据库外部监视诸如insert这样的原子操作并不是最好的主意。您应该依赖于db means on that(触发器、变量、全局计数器)