ALTER TABLE without locking the table?

后端 未结 19 1848
梦毁少年i
梦毁少年i 2020-11-30 17:41

When doing an ALTER TABLE statement in MySQL, the whole table is read-locked (allowing concurrent reads, but prohibiting concurrent writes) for the duration of the statement

相关标签:
19条回答
  • 2020-11-30 18:08

    You should definitely try pt-online-schema-change. I have been using this tool to do migrations on AWS RDS with multiple slaves and it has worked very well for me. I wrote an elaborate blog post on how to do that which might be helpful for you.

    Blog: http://mrafayaleem.com/2016/02/08/live-mysql-schema-changes-with-percona/

    0 讨论(0)
  • 2020-11-30 18:10

    Nope. If you are using MyISAM tables, to my best understanding they only do table locks - there are no record locks, they just try to keep everything hyperfast through simplicity. (Other MySQL tables operate differently.) In any case, you can copy the table to another table, alter it, and then switch them, updating for differences.

    This is such a massive alteration that I doubt any DBMS would support it. It's considered a benefit to be able to do it with data in the table in the first place.

    0 讨论(0)
  • 2020-11-30 18:10

    Temporary solution...

    Other solution could be, add a another table with primary key of the original table, along with your new column.

    Populate your primary key onto the new table and populate values for new column in your new table, and modify your query to join this table for select operations and you also need to insert, update separately for this column value.

    When you able to get downtime, you can alter the original table, modify your DML queries and drop your new table created earlier

    Else, you may go for clustering method, replication, pt-online-schema tool from percona

    0 讨论(0)
  • 2020-11-30 18:10

    The difference between Postgres and MySQL in this regard is that in Postgres it doesn't re-creates a table, but modifies data dictionary which is similar to Oracle. Therefore, the operation is fast, while it's still requires to allocate an exclusive DDL table lock for very short time as stated above by others.

    In MySQL the operation will copy data to a new table while blocking transactions, which has been main pain for MySQL DBAs prior to v. 5.6.

    The good news is that since MySQL 5.6 release the restriction has been mostly lifted and you now can enjoy the true power of the MYSQL DB.

    0 讨论(0)
  • 2020-11-30 18:12

    Not really.

    You ARE altering the underlying structure of the table, after all, and that's a bit of information that's quite important to the underlying system. You're also (likely) moving much of the data around on disk.

    If you plan on doing this a lot, you're better off simply padding the table with "dummy" columns that are available for future use.

    0 讨论(0)
  • 2020-11-30 18:15

    Since you asked about other databases, here's some information about Oracle.

    Adding a NULL column to an Oracle table is a very quick operation as it only updates the data dictionary. This holds an exclusive lock on the table for a very short period of time. It will however, invalidate any depedant stored procedures, views, triggers, etc. These will get recompiled automatically.

    From there if necessary you can create index using the ONLINE clause. Again, only very short data dictionary locks. It'll read the whole table looking for things to index, but does not block anyone while doing this.

    If you need to add a foreign key, you can do this and get Oracle to trust you that the data is correct. Otherwise it needs to read the whole table and validate all the values which can be slow (create your index first).

    If you need to put a default or calculated value into every row of the new column, you'll need to run a massive update or perhaps a little utility program that populates the new data. This can be slow, especially if the rows get alot bigger and no longer fit in their blocks. Locking can be managed during this process. Since the old versino of your application, which is still running, does not know about this column you might need a sneaky trigger or to specify a default.

    From there, you can do a switcharoo on your application servers to the new version of the code and it'll keep running. Drop your sneaky trigger.

    Alternatively, you can use DBMS_REDEFINITION which is a black box designed to do this sort of thing.

    All this is so much bother to test, etc that we just have an early Sunday morning outage whenever we release a major version.

    0 讨论(0)
提交回复
热议问题